(PART) Group project

Intro

Welcome to the introduction to the group project!

Here you will find all important points related to the group project. In the following subchapters, you can find explanations for each step you should take in your group project. Generally, the group project comprises two parts. In the first part, you will work with your group on creating and conducting a survey. Once you have created a draft of your questionnaire, you will receive a feedback from us. After implementing the feedback, you will be ready to start collecting data! In the second part, you will have a chance to apply statistical knowledge acquired in the class and from online script. In fact, you will analyze the collected data, present your findings and finally submit your final report (R code and presentation).

Groups

Topics for the group project

Topic Description
Car-sharing vs. vehicle ownership Develop a questionnaire to explore the attractiveness of car sharing options for consumers (e.g., Car2go). Are consumers willing and planning to substitute a personal vehicle through car sharing option? Is car sharing likely to affect the amount of driving? Which factors influence these decisions?
Student canteen (Mensa) and the WU campus* Develop a questionnaire to measure students‘ attitudes and its drivers (e.g., quality of meals, price, etc.) toward the canteen and other restaurantson the campus.
Privacyin social media –consumers’ willingness to switch to a secure messaging service Develop a questionnaire to measure consumers’ willingness to switch from WhatsApp to a secure messaging service (e.g., Threema). What are the main motives (e.g., security concerns, costs, usability, etc.), and are consumers willing to pay for the secure service provider?
Consumer preferences for fair-trade products in the apparel industry Develop a questionnaire to measure consumers’ preferences for sustainable brands and eco fashion. Conduct an experiment to determine whether there are different perceptions regarding the “Fair Trade” effect.
The climate debate and green consumption The climate debate is currently on the top of the agenda of many news outlets. Some public figures that strongly favor one side dominate and emotionalize the debate (e.g., Greta Thunberg, DonaldTrump). Explore in how far consumers are willing to change their behavior (e.g.,cut air-travel) to help protect the environment. What factors influence the willingness to change (e.g., social factors, convenience)?
Self-driving cars Companies such as Google heavily invest in the development of self-driving cars. Develop a questionnaire to measure consumers attitude and usage intention for self-driving cars. What are the drivers and deterrents of the consumers’ willingness to adopt this innovation?
Freemium businessmodels in the music industry Many music streaming services (e.g., Spotify) offer a baseline version free of charge to consumers but charge for a premium version with additional features. Develop a questionnaire to measure consumers’ attitude towards legal music streaming providers.What factors influence the attitude(e.g., occupation, gender, usage behavior etc.), and how could companies motivate consumers to convertto the premium version of the service?
Consumers’ attitude towards legal video streaming providers and piracy Video streaming providers like Netflix record a continuous increase in registered users. On the other hand, illegal video streaming portals (e.g., Popcorn Time) are heavily used by other consumers. Develop a questionnaire to measure consumers’ attitude and drivers (e.g. occupation, gender, usage behavior etc.) towards legal video streaming providers. What could be reasons for piracy?
Impact of Coronavirus on online shopping services More and more people use online shopping services (e.g., Amazon Fresh, BillaOnline) to buy groceries since Coronavirus started spreading. Develop a questionnaire to measure consumers’ attitude and its drivers (e.g., price, service) towards the online services during and before Coronavirus outbreak. Are consumers less price sensitive when shopping online than in the offline stores? How likely are consumers to continue using online shopping services in the future?
Implications of Coronavirus on brand loyalty After outbreak of Coronavirus many consumers strayed from normal shopping patterns and began stockpiling products. Many retailers were working around the clock with their selling partners to ensure availability on all of our products, and bring on additional capacity. How did it affect brand loyalty? Did consumers try out alternative brands? If so, by what factors were consumers driven to change the brand they used before?
Consumers’ willingness to pay for organic products Develop a questionnaire to measure consumers’ willingness to pay for organic products (e.g., milk). How much are consumers willing to pay for organic milk vs. conventional milk? What is the observed price premium? How does this vary across consumers? What are the drivers? Does it reflect a desire to achieve better health, eat better quality food, or to contribute to environmental protection?
The most liveablecity in the world Vienna is frequently listed as one of the most liveablecities in the world (e.g., by the Economist Intelligence Unit). Develop a questionnaire to investigate the reasons why Vienna ranksso high in different rankings. What are the factors that contribute to its image? Are there differences between different groups of people?

Part 1: Before collecting data

An aim of this course is to develop your ability to translate business problems into actionable research questions and to design an adequate research plan to answer these questions. Therefore, you need to be equiped with knowledge on how to create a survey and properly conduct a research.

Generally, what you can expect from the survey design is similar to what one experiences in a relationship. If you try to take more than you commit, it doesn’t work out. Now on a serious note, if you follow guidelines mentioned here, you will certainly avoid usual traps your fellow collegues were caught in.

In a research process, conducting a survey is a part of (primary) data collection. Before we collect data, we have to make sure that preceding steps are correctly done. However, in the following sections we will focus on the process of designing a questionnaire. Eventually, you will be able to collect relevant data and apply appropriate statistical tests.

Note that this assignment may require you to deal with and integrate knowledge that has not yet been covered in class! Students are expected to read ahead and collect additional information to the extent to which their project requires this.

Research design

As you aim to conduct a real marketing research, before you start writing down questions for a questionnaire, you need to come up with a research design. In particular, you should review the research questions, hypotheses and characteristics that influence the research design.

If you are interested in the causal effect of one particular (independent) variable on another (dependent) variable, think about an experimental design that might allow you to manipulate this variable. In this case, you particularly have to decide on the following:

  • Which variable to manipulate?
  • Whether to use a between-subjects or within-subjects design?
  • The cause-effect sequence (the cause must occur before the effect)
  • The number of experimental conditions
  • Potential interactions and relationships with other variables (does the effect depend on another variable?)

What you need to be careful about is the effect of reversed causation. The effect refers to the situation where the causal relationship could possible have an opposite direction from what we assumed at the first place. For instance, it is often assumed that an increase in individual income leads to increase in well-being (happiness). However, some researches suggest that this causation could have an opposite direction, i.e. that actually increase in well-being of an individual leads to an increase in income.

Here are some examples of causal research design applications:

  • To assess how a product’s country-of-origin impacts attractiveness across different countries.
  • To analyse the effects of rebranding on customer loyalty.

If you would like to analyze the effects of multiple categorical or continuous (independent) variables on one continuous (dependent) variable, you might use a regression model. When doing this, you particularly have to decide on:

  • How to measure the dependent variable (DV). This is particularly important, since you need a variable that is powerful in uncovering variation between subjects (e.g., open-ended questions, such as “How much are you willing to pay for this product” are good candidates). Moreover, you also need to consider the nature of your DV,i.e. whether it is an interval variable, ordinal or categorical variable. The nature of your DV will heavily influence your choice of a correct statistical test.

  • How to measure the independent variables (IV) (single-item vs. multi-item scales, categorical vs. continuous). Bear in mind that the nature of the IV, together with DV, affects your choice of a statistical test as well.

  • What other variables might cause the effect that you would like to investigate (to prevent omitted variable bias, i.e. variables that are not part of your model but still influence the dependent variable).

  • Potential interactions (e.g., is the effect of variable X stronger for group A vs. B?)

Survey method

In the next step you should review the type of survey method you will use.

At this point you need to think in which setting you aim to conduct your survey. For instance, should you do it in a face-to-face setting or rather online. Here you can find some advantages and disadvantages of online surveys:

Here is the list of the online tools you can use to conduct an online survey (usually for free):

For the purpose of this course, we suggest to use Qualtrics.

A questionnaire creation in Qualtrics starts with creation of a Qulatrics project. Each project consists of a survey, distribution record, and collection of responses and reports. There are three ways to create a questionnaire. First, you can create a new survey project from scratch. Second, you can create a new questionnaire from a copy of an existing questionnaire. Eventually, you can create from a template in your Survey Library, or from an exported QSF file.

In order to create a completely new questionnaire, you need to do the following:

Go to the Projects page by clicking the Qualtric XM logo or clicking Projects on the top-right.

Create new project by clicking the blue button on the right side.
In the “Create your own” section click on the survey button.

Enter a name for your survey and get started with a survey creation.

If you would like to create a new questionnaire on a basis of an already existing one, then you choose “From a Copy”. Subsequently, you need to indicate the questionnaire you would like to copy. Now you are good to go!

If there is a questionnaire in the Qualtrics Library you would like to use, then you need to choose “From Library”, and indicate one library name in the dropdown menu.

Some useful tips when creating a questionnaire in Qualtrics:

  • Add a progress bar so that respondents know how many pages are left (see “Look & Feel” menu in Qualtrics).

  • Remember to activate the “Force Response” field under “Validation Options” if you don’t want to allow respondents to skip questions.

  • Check the usability on mobile devices using the preview option (make sure the “Mobile friendly” option is checked).

Questionnaire

After you set up everything, you should develop 20 - 25 questions. However, there are some important objectives to keep in mind while developing a questionnaire:

  • Information you are primarily interested in (dependent variable)
  • Information which might explain the dependent variable (independent variables)
  • Other factors related to both dependent and independent factors
  • Who’s answering the questions?

If you have sorted out all answers on the previous questions, you are ready to start writing the content. Again, here are some important things to remember:

  • The purpose of the questionnaire
  • Why it is important for you and why it could be useful for the respondent
  • How long it should take to complete & the final date for a reply
  • Ask questions in a logical order & use the right type of questions
  • Aim for brevity & use simple language

Questionnaire and research design

The questionnaire design should be aligned with the research design! Therefore, in the following sections we will explain some suggested steps on how to approach questionnaire creation.

Let’s start with what is a questionnaire. A structured questionnaire is a research instrument designed to elicit specific information from a sample of a target population. Usually it is used in a standardized way with fixed-alternative questions (same questions and response options for all respondents).

An objective of a questionnaire is threefold:

  • to translate the information need into a set of specific questions that the respondent can and will answer,
  • to motivate, and encourage respondents to become involved, to cooperate, and to complete the questionnaire,
  • to minimize response error.

Content in a questionnaire

In this step you are starting to work on the content of you questions.

At the beginning of the questionnaire you should give a brief introduction to your respondents in the context of your research and the content of the questionnaire. Try to use simple language and avoid technical terms. Additionally, in the introduction you should state how long the survey will approximately take.

When you start thinking about the questions to ask, there are several points to consider:

  • Is the question necessary?
  • Will I obtain the needed information?
  • Are several questions needed instead of one?
  • What type of data can I collect by asking that question (categorical or continuious)?

In your survey try to avoid asking double-barrelled questions.Those are a single question that attempts to cover two issues. Such questions can be confusing to respondents and result in ambiguous responses. Instead, you might ask multiple questions in order to obtain the inteded information.

\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

Do you think Nike Town offers better variety and prices than other Nike stores?

\vspace{-0.10in}
\vspace{-0.10in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

Do you think Nike Town offers better variety than other Nike stores?
Do you think Nike Town offers better prices than other Nike stores?

\vspace{-0.10in}
\vspace{-0.10in}
don't know how to handle 'block' engine output

Inability and unwillingness to answer

The quality of collected data you highly depends on your ability to address correct participants. Therefore, you need to make sure that your respondents are able to meaningfully answer your questions.

Examples:

  • Not every household member might be informed about monthly expenses for groceries purchases if someone else makes these purchases.
  • Use filter questions that measure familiarity and product use.
  • Include a “don’t know” option.
  • If you ask participants for monteray values (e.g. how much are you ready to pay for the XY product?) across several EU, make sure you indicate correct currency (e.g. HRK for Croatia or HUF for Hungary).
  • Think about how mobile friendly is the layout of your survey (if it is an online survey).
  • Good case practices suggest that there should not be more than 2 questions per page (for online surveys displayed on mobile phones).

If you are asking participants to recall certain brands for instance, make sure you use unaided recall question:

\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

What brands of soft drinks do you remember being advertised on TV last night?

\vspace{-0.10in}
\vspace{-0.10in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

Which of these brands were advertised last night on TV?
a) Coca-Cola
b) Pepsi
c) Red Bull
d) Evian
e) Don’t know

\vspace{-0.10in}
\vspace{-0.10in}
don't know how to handle 'block' engine output

If you are asking participants to list something, the good case practice is to minimize the effort required by respondents:

\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

Please check all the departments from which you purchased merchandise on your most recent shopping trip to a department store:
a) Women’s dresses
b) Men’s apparel
c) Children’s apparel
d) Cosmetics
e) Jewelry
f) Other (please specify) ___________

\vspace{-0.10in}
\vspace{-0.10in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

Please list all the departments from which you purchased merchandise on your most recent shopping trip to department store X.

\vspace{-0.10in}
\vspace{-0.10in}
don't know how to handle 'block' engine output

In a case you are asking for information that could be considered sensitive (e.g. money, family life, political beliefs, religion), they should come at the end of the questionnaire. Moreover, it is recommendable to provide response categories rather than asking for specific figures:

\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

Which one of the following categories best describes your household’s annual gross income?
a) under 25.001 €
b) 25.001€ to 50.000 €
c) 50.001€ to 75.000 €
d) 75.001€ to 100.000 €
e) over 100.000 €

\vspace{-0.10in}
\vspace{-0.10in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

What is your household’s exact annual income?

\vspace{-0.10in}
\vspace{-0.10in}
don't know how to handle 'block' engine output

Decide on measurement scales and scaling techniques

Every statistical analysis requires that variables have a specific levels of measurement. Measurement scales you choose for your questions in a survey will affect the answers you get and eventually statistical test you can apply. For instance, it would not make sense to compute an average of genders. An average of a categorical variable does not make much sense. Moreover, if you tried to compute the average of genders defined in numeric values (e.g. male=0, female=1), the output would be interpretable.

It is crucial to become familiar with possibilities of each scale before you choose to add another question to your survey. Consequently, chances to obtain data you did not intend to collect and chances that you will not be able to apply tests you intended are significantly lower.

In the following table you can get a quick overview of possibilities per each measurement scale. :

In the table below you can find general procedure for choosing a correct analysis based on the measurement scale of your data and number of variables. It shows statistical analyses we covered during the course and aims to help you choose among them based on the nature of dependent variables on the side, and the nature and the number of your independent variables on the other side:

It is highly recommended to think about what type of data you want to collect and what test to use, before you form a question and add to the survey. We highly recommend you NOT to add questions without thinking what type of data you are going to collect with it. If you do so, you may end up with data you did not want to collect, and moreover, with data unsuitable for the test you intended to use.

Here you can find extremely nice overview of statistical test associated with different types of variables: CHOOSING THE CORRECT STATISTICAL TEST - UCLA

The most frequent types of questions

Here we want to show you the most frequent types of questions students use and what type of data can be collected by using them.

Attaching package: 㤼㸱janitor㤼㸲

The following objects are masked from 㤼㸱package:stats㤼㸲:

chisq.test, fisher.test

Parsed with column specification: cols( .default = col_double(), StartDate = col_character(), EndDate = col_character(), IPAddress = col_logical(), RecordedDate = col_character(), ResponseId = col_character(), RecipientLastName = col_logical(), RecipientFirstName = col_logical(), RecipientEmail = col_logical(), ExternalReference = col_logical(), LocationLatitude = col_character(), LocationLongitude = col_character(), DistributionChannel = col_character(), UserLanguage = col_character(), Q7_MC_sa_country_3_TEXT = col_logical(), Q23_Gender_3_TEXT = col_logical(), Condition = col_character() ) See spec(…) for full column specifications.

Multiple choice question

Multiple Choice with a single answer is a type of closed-ended question that lets respondents select one answer from a defined list of choices.Type of data you obtain is categorical.

Statistical test that you can think of when analysing categorical data:

  • Fisher’s exact test
    • Used when frequency in at least one cell is less than 5 . When frequencies in each cell are greater than 5, Chi-square test should be used
    • 1 dependent variable and 1 independent variable with 2 or more levels/factors
    • Hypothesis: Is there a significant difference in frequencies between values observed in cells and values expected in cells
  • Chi-square test
    • Goodness of fit: when you only have 1 dependent variable and none independent variables
      • Hypothesis: Is there a significant difference in frequencies between values observed in cells and values expected in cells ?
    • Chi-Square Test of Independence: when you have 1 dependent variable and 1 independent variable with 2 or more levels/factors.
      • Hypothesis: Is there an association between categorical variable X and categorical variable Y?
  • Binomial logistic regression
    • Used when you have an independent variable of at least interval scale and dependent variable is a categorical variable that can take on exactly two values (1 or 0, i.e., yes or no).
  • Categorical variables can be used as predictors in regression (as dummy variables).

It is important to distinguish multiple choice questions with single and multiple answers (which will be presented later) as their analysis looks differently.

For the analysis of results collected with multiple choice question with multiple possible answers, we can use Cochran’s Q test. Although we did not mention it before, it is not too different from what you have already learned about other tests.

The Cochran’s Q test and associated multiple comparisons require the following assumptions:

  1. Responses are dichotomous and from k number of matched samples.
  2. The subjects are independent of one another and were selected at random from a larger population.
  3. The sample size is sufficiently “large”. (As a rule of thumb, the number of subjects for which the responses are not all 0’s or 1’s, n, should be ≥ 4 and nk should be ≥ 24)

Rank order question

A rank order question asks respondents to compare items to each other by placing them in order of preference. Note that the data obtained from a rank order question shows an order of a respondent’s preference, but not the difference between items. For instance, if it turns out that the most important feature of a fitness tracker for a respondent XY is “Measuring steps” and the second most important feature “Calories burned”, we don’t know for how much more important is the former one in comparison to the latter one.

In order to analyze results from a rank order question, we use Friedman rank sum test.

Friedman rank sum test is used to identify whether there are any statistically significant differences between the distributions of 3 or more paired groups. It is used when the normality assumptions for using one-way repeated measures ANOVA are not met. Another case when Friedman rank rum test is used is when the dependent variable is measured on an ordinal scale, as in our case.

Constant Sum question

If you wish to obtain information about how much one attribute is preferred over another one, you may use a constant sum scale. The total box should always be displayed at the bottom to make it easier for respondents. A constant sum question permits collection of ratio data type. With data obtained we would be able to express the relative importance of the options.

With the data collected we are able to answer the question: what factor is the most important for our respondents when they go out for a dinner?

In order to answer this question we need to conduct a repeated measures ANOVA.

This type of ANOVA is used for analyzing data where the same subjects are measured more than once. In our case we have every respondent measured on each of the factors (locations, price, ambience and customer service). Repeated measures ANOVA is an extension of the paired-samples t-test. This test is also referred to as a within-subjects ANOVA. In the within-subject experimental design the same individuals are measured on the same outcome variable under different time points or conditions.

Text or number entry question

A text or number entry question is a recommended type of question if you are interested in obtaining ratio data type. We will use this type of question together with a constant sum question type to collect data that can be analysed with regression analysis. Note that in this case we treat constant sum data as ratio data and therefore assume that 0 means complete absence.

Scaling techniques

When it comes to scaling techniques, they are meant to study the relationship between objects. The basic scaling techniques classification is on comparative and non-comparative scales.

The noncomparative scale each object is scaled independently of the other objects. The resulting data is supposed to be measured in an interval and ratio scaled.

Comparative scales (or nonmetric scaling) compare direclty the stimulus object. For example, the respondent might be asked directly about his preference between domestic and foreign beer brands. As a result, the comparative data collected can only be interpreted in relative terms. In the following sections we will walk through both types of comparative scales and briefly introduce them.

Comparative scale: Paired Comparison

  • Respondent is presented with two objects and asked to select one according to some criterion.
  • The nature of resulting data is ordinal
  • Assumption of transitivity (if X > Y and Y > Z, then X > Z) enables the paired comparison data to be converted into a rank order. To do so, you need to indetify the number of times the object is preferred by adding up all the matrices.
  • Effective when the number of objects is limited as it requires the direct comparison, and a bigger number of objects makes the comparison becomes unmanagable.
  • Example:
    For each pair, please indicate which of the two brands of beer in the pair you prefer.

Comparative scale: Rank Order

  • Allow a certain set of brands or products to be simultaneously ranked based upon a specific attribute or characteristic.
  • The rank order scaling is a good proxy for to the shopping setting as there are simultaneous comparisons of objects.
  • The rank order scaling results in the data of ordinal nature.
  • Example:
    Rank the various brands of beer in order of preference. Begin by picking out the one brand that you like most and assign it a number 1. Then find the second most preferred brand and assign it a number 2. Continue this procedure until you have ranked all the brands of beer in order of preference. No two brands should received the same rank number.

Comparative scale: Constant sum

  • Respondents allocate a constant sum of units (e.g., points, dollars) among a set of stimulus objects with respect to some criterion.
  • Constant sum is similar to rank order, but it carries specific units.
  • The resulting data does not just indicate important factors, but also by how much a factor supersedes another one.
  • Constant sum scaling can be used to observe the comparative significance respondents assigned to various factors of a subject.
  • Example:
    There are 8 attributes of bottled beers. Please allocate 100 points among the attributes so that your allocation reflects the relative importance you attach to each attribute.

  • Basic analysis of constant-sum data involves tabulation of responses and presenting them as either quantities (e.g., “on average, 7 points were allocated to”high alcohol level“), or, as proportions (”On average, 7% of points were allocated to “high alcohol level”).

Non-Comparative Scales: Continuous Rating Scales

  • Participants rate the objects by placing a mark at the appropriate position on a line that runs from one extreme of the criterion variable to the other.
  • One of the advantages of the continuous rating scale is that it is easy to administer.

  • Once the ratings are collected, you can splits up the obtained ratings into categories and then assign those depending on the category in which the ratings fall.

Non-Comparative Scales: Itemized Rating Scales

  • The respondents are provided with a scale that has a number or brief description associated with each category.
  • The categories are ordered in terms of scale position, and the respondents are required to select the specified category that best describes the object being rated.
  • The commonly used itemized rating scales are the Likert, semantic differential and Stapel scales.
Itemized Rating Scales: Likert scale
  • Requires respondents to indicate their attitude towards the given object through the degree of agreement or disagreement with each of a series of statements within typically five or seven categories.
  • Reversed code of some items increases validity.
  • One limitation is time required to answer a question on a Likert scale. Compared to other itemized scaling techniques, Likert scale is more time consuming as each respondent is required to read every statement given in a questionnaire before assigning a numerical value to it.

In the table below you can find a couple of commonly measured constructs in marketing research such as attitude, importance, purchase intention and similar.

Itemized Rating Scales: Semantic Differential
  • Typically, participants rate objects on a number of itemized, seven-point rating scales bounded at each end by one of two bipolar adjectives.

  • Semantic differential can measure respondent attitudes towards something (products,concepts, items, people…).

  • It helps you find the respondent’s position is on a scale between two bipolar adjectives such as “Sweet-Sour” or “Bright-Dark”. In comparison to Likert scale, which uses generic scales (e.g. extremely dissatisfied to extremely satisfied), semantic differential questions are posed within the context of evaluating attitudes.

  • Widely used rating scale in marketing research due to its versatility

When creating a semantical difference question, you should consider the following:

  • Number of categories:

  • Balanced vs. unbalanced:

  • Odd/even number of categories:

  • Forced vs. non-forced response

  • Verbal description:

Questionnaire structure

The sequence of questions in a questionnaire could play important role. For instance, more sensitive questions (such as demographic-related questions) are usually placed at the end as they can trigger change in respondent’s behavior.

If you plan to conduct an online survey, then you need to think about the respondent’s experience while doing your questionnaire. For instance, spread the content over more short pages and do not have fewer long pages. In online surveys, two questions on one page is a useful rule of thumb. Generally, respondents are reluctant to read and fill out long questionnaire pages. Hence, long pages will lead to a higher dropout rate. In order to reduce dropout rate state how long the survey will approximately take in the introduction of the questionnaire. Take into account that tools like Qualtrics provide the estimated response time in the survey overview.

Consider that the most of people usually use their phones to fill it out. Think about how the questionnaire will appear on a phone screen too. In that regard, think of length of questions especially.

In the end, the questionnaire structure has to be aligned with the research design. For example, if your research design features an experiment, this needs to be reflected in the questionnaire (e.g., you need to assign the respondents randomly to the experimental conditions in case of a between-subjects comparison).

Questionnaire structure for a between-subjects design

In a between-subject design you randomly assign each respondent to different experimental conditions. They would then complete tasks only in the condition to which they are assigned.

For instance, we would like to test the effect of two advertisements on purchase intention. Therefore, one group of (randomly assigned) respondents will be exposed to one advertisement version while the other group (of randomly assigned respondents) will be exposed to another version. After that, both groups of respondents should express their willingness to buy the advertised product. Evenutally, if the dependent variable (e.g. willingness to buy) is measured on interval or ratio scale, then you can use independent t-test to compare group means. The whole experimental design should be organised as following:

Questionnaire structure for a within-subjects design

This type of experimental design involves exposing each respondent to all of the user experimental conditions you’re testing. This way, each respondent will test all of the conditions.

For instance, we would like to test again the effect of two advertisements on purchase intentions, but this time in a within-subject design. First, each respondent will be exposed to the first version of advertisement and right after that asked to rate his/her willingness to buy the advertised product. Subsequently, each participant will be shown another version of advertisement and again rate his/her willingness to purchase the advertised product. Finally, we can compare group means with paired sample t-test (given that data is measured on interval or ratio scale).

Question wording

Generally, question wording should enable each respondent to understand questions and to be able to answer them with reliability. Reliability means that, if a respondent was asked the same question again, he/she would give the same answer again. A number of common problems regarding the question wording have been identified, so we will address the most important ones.

In order to ensure reliability, the issue in terms of who, what, when and where should be defined in each question.

\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

Example: Which brand of shampoo do you use?
Who (the respondent): It is not clear whether this question relates to the individual respondent or the respondent’s total household.
What (the brand of shampoo): It is unclear how the respondent is to answer this question if more than one brand is used.
When (unclear): The time frame is not specified in this question. The respondent could interpret it as meaning the shampoo used this morning, this week, or over the past year.
Where (not specified): At home, at the gym? Where?

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

A more clearly defined question is:
Which brand or brands of shampoo have you personally used at home during the last month? In the case of more than one brand, please list all the brands that apply.

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output

Use ordinary words. Words should match the vocabulary level of the participants.

\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

“Do you think the distribution of soft drinks is adequate?”

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

“Do you think soft drinks are easily available when you want to buy them?”

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output

Avoid double negative form. Double negative question forms can confuse respondents, especially when they need to answer with “Agree” or “Disagree”.

\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

Do you think that it is not uncommon that boys play basketball?

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

In your opinion, is it common that boys play basketball?

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output

Avoid leading questions.Leading questions clue the participant to what the answer should be. Such questions introduce a bias in a particular direction.

\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

“Is Colgate your favorite toothpaste?”

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

“What is your favorite brand of toothpaste?”

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output

Avoid ambiguous words. Words such as usually, normally, frequently, often, regularly, and other similar words, do not define frequency clearly enough.

\vspace{-0.1in}
Incorrect
\vspace{-0.1in}
don't know how to handle 'block' engine output

“In a typically month, how often do you go to a movie theater to see a movie?”
a) Never
b) Occasionally
c) Sometimes
d) Often
e) Regularly

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output
\vspace{-0.1in}
Correct
\vspace{-0.1in}
don't know how to handle 'block' engine output

“In a typically month, how often do you go to a movie theater to see a movie?”
a) Less than once
b) 1 or 2 times
c) 3 or 4 times
d) More than 4 times

\vspace{-0.1in}
\vspace{-0.1in}
don't know how to handle 'block' engine output

Choose adequate order

One of the last steps in a process of designing a questionnaire is choosing adequate order of questions and instructions for respondents.

At the beginning, you should provide a short and easy-to-understand introduction to the topic. Use simple language and avoid technical terms (e.g., not many people will know the terms “manufacturer brand” and “store brand”). Additionally, in the introduction you should state how long the survey will approximately take.

The opening questions should be interesting, simple and non-threatening. They are crucial because it is the respondent’s first exposure to the questionnaire and is likely to set the tone for the rest of questions in the questionnaire. If too difficult to understand, or sensitive in some way, respondents are likely to stop answering your questions. Qualifying questions (or screening questions) should serve as the opening questions (if applicable). Their purpose is to identify a potential respondent that is eligible to proceed with the research survey.

After the opening part, you should establish an optimal question flow. General questions should precede the specific questions. Questions on one subject, or one particular aspect of a subject, should be grouped together. It may feel confusing to be asked to return to some subject they thought they already gave their opinions about.

As respondents are moving towards the end of the questionnaire, they are likely to become increasingly indifferent and might give careless answers. Therefore, questions of special importance should ideally be included in the earlier part of the questionnaire.

Finally, you should pay particular attention to provide all prescribed definitions and explanations before you ask a question. This ensures that the questions are understood in consistent way by every respondent.

Test your questionnaire

Finally, before you distribute the final questionnaire, there are some things to consider. First, you should always pretest your questionnaire before sharing it! Test all aspects of the questionnaire (content, wording, sequence, form & layout, etc.). If possible, use respondents in the pretest that are similar to those who will be included in the actual survey. Ideally, the pretest sample size should be small (in a real scenario this could vary from 15 to 30 respondents; for the group project, a lower number will be sufficient). After each significant revision of the questionnaire, conduct another pretest, using a different sample of respondents. Eventually, code and analyze the responses obtained from the pretest so that you make sure that you collected information you intended to collect.

After testing your questionnaire you should be able to determine whether:

  • The questions are properly framed
  • The questions wording triggers any biases
  • The questions are placed in the optimal order
  • The questions are understandable
  • Specifying questions are needed or some need to be eliminated

Pitch, revision & submission

At this stage, you should be ready for pitching your questionnaire. Please keep in mind the timetable.

Date_A Time_A Date_B Time_B Task Chapters Link
Oct. 21 11:59PM Oct. 25 11:59PM * Submit questionnaire draft 10
Oct. 23* 09:00AM - 02:30PM Oct. 27* 02:00PM - 08:00PM * Coaching: Questionnaire design (live video coaching) 10 TBC
Nov. 1 11:59PM Nov. 4 11:59PM * Submit revised questionnaire 10
Note: Dates and times are indicated for groups A and B respectively.
Sessions indicated with '*' are group coaching sessions. Slots of 45 min. are assigned to each group within the indicated times.

Part 2: Collecting data and analysis

Data analysis

Parsed with column specification: cols( .default = col_double(), StartDate = col_character(), EndDate = col_character(), IPAddress = col_logical(), RecordedDate = col_character(), ResponseId = col_character(), RecipientLastName = col_logical(), RecipientFirstName = col_logical(), RecipientEmail = col_logical(), ExternalReference = col_logical(), LocationLatitude = col_character(), LocationLongitude = col_character(), DistributionChannel = col_character(), UserLanguage = col_character(), Q7_MC_sa_country_3_TEXT = col_logical(), Q23_Gender_3_TEXT = col_logical(), Condition = col_character() ) See spec(…) for full column specifications.

In this chapter we will encounter the nature of data you collect when conducting a survey. It will help you choose a type of a question depending on the nature of data you want to collect and on the type of statistical tests you want to apply.

Multiple choice with a single answer

Multiple Choice with a single answer is a type of closed-ended question that lets respondents select one answer from a defined list of choices.

Type of data you obtain is categorical, and the output comes in the following form:

What to do with this data now? First, we need to load it in R and prepare for analysis. The numbers you see in the output R recognizes as numeric. In order to conduct statistical modeling and properly visualize our results, we need to convert our data to a factor class.

A factor (or coding variable) represents different groups of data by using numbers (integers). In fact, factors appear as numeric variables, but they hold meaning of labels/names of data groups, i.e. nominal variable. These data groups are represented in a form of ‘levels’.
In our case, our multiple choice question output will contain 4 data groups (‘Grocery Store’, ‘Online shop’, ‘Specialised coffee shop’, ‘other’) after converting it to factor:

# Convert numeric value to factors
qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?' <- factor(qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?', levels = c(1:5), labels = c('Never','1-2 hours','3-4 hours','5-6 hours','more than 6 hours'))

qualtrics$` Selected Choice_1` <- factor(qualtrics$` Selected Choice_1`,levels = c(1:2),labels = c("Male","Female"))

qualtrics$` Selected Choice` <- factor(qualtrics$` Selected Choice`, levels = c(1:2), labels=c("Austria","Germany"))


# Table
table(qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?')

            Never         1-2 hours         3-4 hours         5-6 hours 
               19                18                22                35 
more than 6 hours 
               23 
table(qualtrics$` Selected Choice`)     #countries

Austria Germany 
     35      82 
table(qualtrics$` Selected Choice_1`)   #gender

  Male Female 
    49     68 

Second, you might want to visualize your results. In order to do so, the data format needs to be in the appropriate format.Here we proceed with data format adaptation from the point where we stopped:

# Converting long format to the visualisation-friendly format
mlc_visualisation <- as.data.frame(table(qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?'))

# Naming columns
names(mlc_visualisation) <- c('Time','Count')

# Observing
knitr::kable(mlc_visualisation)

Time Count
Never 19
1-2 hours 18
3-4 hours 22
5-6 hours 35
more than 6 hours 23

NA

The simplest way to visualize data obtained from multiple choice question with a single answer is a bar chart:

## Basic bar chart
labels <- as.character(mlc_visualisation$Time) #Save labels for x-axis in the barplot
barplot(mlc_visualisation$Count, # Column to visualize
        xlab='Time', # X-axis label
        ylab = 'Count(answers)', # Y-axis label
        names.arg = labels,
        main = 'How many hours do you spend watching movies or series on Netflix?') # Title

R package ggplot2 allows you to create visually appealing graphs:

## ggplot2 bar chart
library(ggplot2)
p <- ggplot(data=mlc_visualisation, 
             aes(x=Time, y=Count, fill=Time)) +
             geom_bar(stat='identity') + theme_minimal() + labs(title = "In a typical week, how many hours do you spend watching movies or series on Netflix?")
p

Another R library which can help you make amazing interactive charts in a minute is plotly. Here we use a function called ggplotly(), which allows you to turn any ggplot2 chart interactive. Since we have already created a bar chart using ggplot2 and saved it as “p”, we will just turn it into plotly graph:

## ggplotly bar chart

library(plotly)
ggplotly(p)

An improved version of ggplot2 package is the packaged called ggvis, which is still in developing:

## ggvis bar chart

library(ggvis)
ggvis(mlc_visualisation, 
      x = ~Time, 
      y = ~Count, 
      fill=~Time)

Data type collected from the previous question is ordinal as we are able to make a natural order of the levels. Since it is ordinal data type, it belongs to categorical data. For the analysis of categorical data we can use Chi-square test or Fisher’s test if a count for some level is less than 5.

Fischer’s exact

Fisher’s exact test is used to test a hypothesis with data obtained from multiple choice questions with single answer. Results from multiple choice questions with multiple answers are treated with different test.
  • Application: when you have 1 dependent variable and 1 independent variable with 2 or more levels/factors
  • Used when frequency in at least one cell is less than 5 . When frequencies in each cell are greater than 5, Chi-square test should be used.
  • Hypothesis: Is there a significant difference in frequencies between values observed in cells and values expected in cells ? (R for Marketing and Research Analytics)
  • H0: There is no relationship between the two categorical variables.Therefore, two categorical variables are independent. Knowing the value of one variable does not help to predict the value of the other variable.
  • H1: There is a relationship between the two categorical variables.Therefore, two categorical variables are dependent.Knowing the value of one variable helps to predict the value of the other variable.
  • Usually, this type of test is used on 2x2 contingency tables. However, it can be applicable on contingency tables of larger dimensions.

Example: We would like to know whether a number of hours spent watching Netflix depends on the respondents’ country of origin.

# Creation of contingency table
fisher_test_table <-table(qualtrics$` Selected Choice`,qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?')
# Check how our contigency table looks like
fisher_test_table
         
          Never 1-2 hours 3-4 hours 5-6 hours more than 6 hours
  Austria     3         7         6        11                 8
  Germany    16        11        16        24                15
# Since we have a count less than 5, we should apply Fisher's test instead of Chi-square.

# Fisher's test
test <- fisher.test(fisher_test_table)
test

    Fisher's Exact Test for Count Data

data:  fisher_test_table
p-value = 0.575
alternative hypothesis: two.sided
# p-value
test$p.value
[1] 0.5750401

From the output and from test$p.value we see that the p-value is higher than the significance level of 5%. Like any other statistical test, if the p-value is higher than the significance level, we can not reject the null hypothesis.

In our case, not rejecting the null hypothesis for the Fisher’s exact test of independence means that there is no significant relationship between the two categorical variables. Therefore, knowing the value of one variable does not help to predict the value of the other variable.

Chi-square test: Goodness of fit & Independence test

  1. Goodness of fit
    • Application: when you only have 1 dependent variable and none independent variables
    • Hypothesis: Is there a significant difference in frequencies between values observed in cells and values expected in cells ?
    • H0: There is no significant difference between the observed and the expected frequencies.
    • H1: There is a significant difference between the observed and the expected frequencies.
    • If we don’t specify expected frequency per cell (see in the code below), then it is expected that all cells show an eqaul frequency.
    • Example :‘Do the numbers of respondents who are spending different amount of hours watching Netflix significantly differ from each other?
  • Note that we did not assume any specific distribution, so we are assuming that each count will have the same or similar number.
# Creating table 
(mlc_chi_square <- table(qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?'))

            Never         1-2 hours         3-4 hours         5-6 hours 
               19                18                22                35 
more than 6 hours 
               23 
      
# Chi-square test (without given expected values = equal values )
chisq.test(mlc_chi_square)

    Chi-squared test for given probabilities

data:  mlc_chi_square
X-squared = 7.9145, df = 4, p-value = 0.09476

The p-value of the test is higher than 0.05. We can conclude that the numbers of respondents who spent different amount of hours watching Netflix are commonly distributed. Observed distribution does not differ significantly from the expected. This result does not surprise if you take a look at the values for each level in the table we created before conducting the test. There you can see that count of answers in each level is more or less not deviating too much. It is visible if you take a look at the previous visualisations as well.

If we are interested in testing more specific distribution, i.e. expect that 40% of our respondents are watching Netflix 3-4 hours, we can introduce corresponding distribution in the test.

# Expected values in percentages for each alternative. The sum must be 1.
expected_values <- c(0.10, # We expect that 10% of our respondents do not watch Netflix at all ("Never").
                     0.20, # We expect that 20% of our respondents watch Netflix 1-2 hours a week.  
                     0.40, # We expect that 40% of our respondents watch Netflix 3-4 hours a week.
                     0.20, # We expect that 20% of our respondents watch Netflix 5-6 hours a week.
                     0.10 # We expect that 10% of our respondents watch Netflix more than 6 hours a week.
                    )
# Chi-square test with expected values
chisq.test(mlc_chi_square, p=expected_values)

    Chi-squared test for given probabilities

data:  mlc_chi_square
X-squared = 35.607, df = 4, p-value = 3.486e-07

This time the p-value of the test is lower than 0.05.We have an evidence that observed distribution does significantly differ from the expected distribution (10%/20%/40%/20%/10%).

  1. Chi-Square Test of Independence
    • Application: when you have 1 dependent variable and 1 independent variable with 2 or more levels/factors
    • Hypothesis: Is there an association between categorical variable X and categorical variable Y?
    • H0: There is no association between the two variables.
    • H1: There is an association between the two variables.
    • Example: Is there an association between gender and the hours spent watching Neflix during a week?
# Creation of contingency table
chi_square_table <-table(qualtrics$` Selected Choice_1`,qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?')

# Chi-square independence test
chisq.test(chi_square_table)

    Pearson's Chi-squared test

data:  chi_square_table
X-squared = 1.5739, df = 4, p-value = 0.8135

Since the p-value (0.8135) is higher than the significance level (0.05), we cannot reject the null hypothesis. Thus, we conclude that there is no association relationship between gender and number of hours spent watching Netflix. Therefore, we can say that the hours spent is independent from the gender of participant.

Multiple choice with multiple answers

Before we conduct any test, we will do some simple calculations and visualise our data.

# Rename columns
colnames(qualtrics)[38] <- "ja!Naturlich"
colnames(qualtrics)[39] <- "Clever"
colnames(qualtrics)[40] <- "Spar Vital"
colnames(qualtrics)[41] <- "..."

# Replacing NA with 0
qualtrics$`ja!Naturlich`[is.na(qualtrics$`ja!Naturlich`)]=0
qualtrics$Clever[is.na(qualtrics$Clever)]=0
qualtrics$`Spar Vital`[is.na(qualtrics$`Spar Vital`)]=0
qualtrics$...[is.na(qualtrics$...)]=0

# Calculating frequency, percentage of respondents and percentage of cases
df.cochran <- data.frame(Frequnecy = colSums(qualtrics[38:41]),
                         Share_of_respondents = (colSums(qualtrics[38:41])/sum(qualtrics[38:41]))*100,
                                Share_of_cases =((colSums(qualtrics[38:41]))/nrow(qualtrics[38:41]))*100)
# Observing
df.cochran

# Visualisation
barplot(df.cochran[,3], names.arg = row.names(df.cochran), main = "% of Respondents familiar with brands", xlab = "Brand",ylab = "Percentage")

The visualisation above depicts the fact that more than 60% percent of people are familiar with the brand “ja!Naturlich”, while we can not say the same for other brands considered in our question.

For the analysis of results collected with multiple choice question with multiple possible answers, we can use Cochran’s Q test.Although we did not mention it before, it is not too different from what you have already learned about other tests.

The Cochran’s Q test and associated multiple comparisons require the following assumptions: 1. Responses are dichotomous and from k number of matched samples. 2. The subjects are independent of one another and were selected at random from a larger population. 3. The sample size is sufficiently “large”. (As a rule of thumb, the number of subjects for which the responses are not all 0’s or 1’s, n, should be ≥ 4 and nk should be ≥ 24)

In a within-subjects experiment design with three or more observations of a dichotomous(= just two levels such as “Yes” or “No”) categorical outcome, you utilize Cochran’s Q test to assess main effects.Similarly, in our multiple choice question with multiple answers we have the same respondent going through three or more potential answers with dichotomous(=yes or no) categorical outcome.

library(nonpar)

# Creation of matrix
#matrix.cochran <- cbind(qualtrics$`ja!Naturlich`,
#                   qualtrics$Clever,
#                   qualtrics$`Spar Vital`,
#                   qualtrics$`...`)
# Turning NAs to 0
#matrix.cochran[is.na(matrix.cochran)]=0

# Cochran test                   
#cochrans.q(matrix.cochran, alpha = 0.05)

The p-value less than 0.05 indicates that there is enough evidence to conclude that some of the store brands are better known among our respondents than other. In order to take a closer look at it, we need to conduct a post hoc test.

library(DescTools)
list.cochran <- list(qualtrics$`ja!Naturlich`,
                   qualtrics$Clever,
                   qualtrics$`Spar Vital`,
                   qualtrics$...) # imaginary brand

# Replacing NAs in the list with 0 in order to be able to run the test
list.cochran <- rapply(list.cochran, f=function(x) ifelse(is.na(x),0,x), how="replace" )

# Post hoc test (Dunn Test)
DunnTest(list.cochran, method="bonferroni")

 Dunn's test of multiple comparisons using rank sums : bonferroni  

    mean.rank.diff    pval    
2-1            -36  0.1093    
3-1            -18  1.0000    
4-1            -74 7.3e-06 ***
3-2             18  1.0000    
4-2            -38  0.0761 .  
4-3            -56  0.0014 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

From the results of the Dunn Test, we can see that there is a big difference between 1 (“ja!Natürlich”) and 4(“…”), as well as between 4(“…”) and 3(“Spar Vital”).

Rank order question

A rank order question asks respondents to compare items to each other by placing them in order of preference. Note that the data obtained from a rank order question shows an order of a respondent’s pereference, but not the difference between items. For instance, if the the most important feature of a fitness tracker for a respondendt XY is “Measuring steps” and the second most important feature “Calories burned”, we don’t know for how much more important is the former one in comparison to the latter one.

Intuitive question to ask is the following: which feature of the fitness tracker is the most important for our respondents?

We can answer this question by calculating a mean rank for each feature. Before we do so, we will create a separate data frame and add columns of the response data.

rank.data <- data.frame(qualtrics$` Measuring steps`,
                        qualtrics$` Calories burned`,
                        qualtrics$` Measuring heartbeat`,
                        qualtrics$` Exercise tracking`,
                        qualtrics$` Measuring distance`)
colnames(rank.data)<-c("Measuring steps","Calories burned","Measuring heartbeat","Exercise tracking","Measuring distance")

First information we would like to know is how many preference combinations there are, and how repetitive they are. We can obtain that information by creating a summary of the ranking data frame we created.

library(pmr)
Loading required package: stats4
test <- rankagg(rank.data)
test
                 n
 [1,] 2 1 3 4 5 10
 [2,] 1 3 2 4 5 19
 [3,] 2 3 1 4 5 17
 [4,] 1 2 4 3 5  4
 [5,] 4 2 1 3 5  3
 [6,] 3 2 1 5 4 15
 [7,] 1 3 5 2 4 10
 [8,] 1 2 4 5 3 10
 [9,] 2 4 1 5 3  9
[10,] 1 2 5 4 3  9
[11,] 5 4 3 1 2  3
[12,] 2 3 4 5 1  8

The matrix we received as an output is the summary of our ranking data. It shows that, for instance, the preference combination “2,1,3,4,5” repeats 10 times in the data frame. More specifically, it means that there are 10 respondents who prefer the item 2(“Calories burned”) the most, then the item 1(“Measuring steps”), and so on.

Now we can calculate the mean rank for each feature and conclude which feature is the most important to our respondents:

# Mean rank of each fitness tracker feature
destat(test)$mean.rank
Descriptive statistics of ranking data: 
$mean.rank: mean ranks; $pair: pairs; $mar: marginals
[1] 1.811966 2.581197 2.598291 4.051282 3.957265

As we can observe from the output, the item 1(“Measuring steps”) shows the best mean rank among all items. Therefore, we can assume that the “Measuring steps” is most important for our respondents. However, in order to statistically prove it and become sure that this is not just by mere chance, we can conduct Friedman rank sum test.

Friedman rank sum test is used to identify whether there are any statistically significant differences between the distributions of 3 or more paired groups. It is used when the normality assumptions for using one-way repeated measures ANOVA are not met. Another case when Friedman rank rum test is used is when the dependent variable is measured on an ordinal scale, as in our case.

Before we conduct the Friedman rank sum test, we will visualise our data:


Attaching package: 㤼㸱rstatix㤼㸲

The following object is masked from 㤼㸱package:janitor㤼㸲:

    make_clean_names

The following object is masked from 㤼㸱package:stats㤼㸲:

    filter

Registered S3 method overwritten by 'broom.mixed':
  method      from 
  tidy.gamlss broom
Registered S3 methods overwritten by 'lme4':
  method                          from
  cooks.distance.influence.merMod car 
  influence.merMod                car 
  dfbeta.influence.merMod         car 
  dfbetas.influence.merMod        car 
In case you would like cite this package, cite it as:
     Patil, I. (2018). ggstatsplot: "ggplot2" Based Plots with Statistical Details. CRAN.
     Retrieved from https://cran.r-project.org/web/packages/ggstatsplot/index.html
# We have just turned our data frame from the wide format to the long format by using function melt(). If we take a look at head and tail of our new data frame, we can see that it contains just two columns, "Rank" and "Feature".

rank.data.long <- reshape2::melt(rank.data,value.name = "Rank",variable.name = "Feature", stringsAsFactors=TRUE)
No id variables; using all as measure variables
attributes are not identical across measure variables; they will be dropped
tail(rank.data.long)
head(rank.data.long)

# Visualisation
ggstatsplot::ggwithinstats(
  data = rank.data.long,
  x = Feature,
  y = Rank,
  type = "np",
  pairwise.comparisons = TRUE, # show pairwise comparison test results
  title = "What features are important to you when evualting fitness trackers?")

Already from the advanced visualisation, that includes Friedman rank sum test and pairwise comparison, we can have an insight in significance of differences among features.

# Friedman test 
friedman.test(as.matrix(rank.data))

    Friedman rank sum test

data:  as.matrix(rank.data)
Friedman chi-squared = 176.42, df = 4, p-value < 2.2e-16

Friedman rank sum test has a p-value lower than 0.05, so we can conclude that here are significant differences between at least two features (what we have already seen in our visualisation). Even though we have identified differences between preferences towards features in our advanced visualisation, we will conduct a post hoc test in order to demonstrate traditional way of calculating pairwise comparisons.

knitr::kable(wilcox_test(Rank ~ Feature, paired = TRUE, p.adjust.method = "bonferroni", data = rank.data.long))
.y. group1 group2 n1 n2 statistic p p.adj p.adj.signif
Rank Measuring steps Calories burned 117 117 1369.0 0.000000 0.000 ****
Rank Measuring steps Measuring heartbeat 117 117 2231.0 0.000753 0.008 **
Rank Measuring steps Exercise tracking 117 117 354.0 0.000000 0.000 ****
Rank Measuring steps Measuring distance 117 117 367.5 0.000000 0.000 ****
Rank Calories burned Measuring heartbeat 117 117 3214.5 0.512000 1.000 ns
Rank Calories burned Exercise tracking 117 117 610.5 0.000000 0.000 ****
Rank Calories burned Measuring distance 117 117 940.0 0.000000 0.000 ****
Rank Measuring heartbeat Exercise tracking 117 117 1235.0 0.000000 0.000 ****
Rank Measuring heartbeat Measuring distance 117 117 1307.5 0.000000 0.000 ****
Rank Exercise tracking Measuring distance 117 117 3534.5 0.816000 1.000 ns

The output table provides us with p-values referring to significance of difference in mean ranks of each pair. For instance, the first 4 rows proves that the differences between the mean rank of the feature “Measuring steps” and each of the rest of features are significant. Consequently, we can conclude that this feature is by far the most important among our respondents.

Another question that may be interesting to explore is whether there are any complementary features ? Or features which overlap each other in its functionality? In order to have a look at that, we can investigate the correlation between ranks assigned to each feature.

#Correlation Matrix
cor.matrix<-cor(rank.data, method=c('spearman'))
cor.matrix
                    Measuring steps Calories burned Measuring heartbeat
Measuring steps          1.00000000     -0.04651331          -0.6569094
Calories burned         -0.04651331      1.00000000          -0.2221626
Measuring heartbeat     -0.65690943     -0.22216264           1.0000000
Exercise tracking        0.29633223     -0.10838758          -0.3255840
Measuring distance      -0.05958032     -0.11694481          -0.3817895
                    Exercise tracking Measuring distance
Measuring steps             0.2963322        -0.05958032
Calories burned            -0.1083876        -0.11694481
Measuring heartbeat        -0.3255840        -0.38178948
Exercise tracking           1.0000000        -0.47176821
Measuring distance         -0.4717682         1.00000000

At the first glance we can observe a lot of negative values, meaning that many features correlate negatively relative to each other. In order to make the interpretation easier, we will try to visualise correlations in a form of a correlation matrix.

library(ggcorrplot)

Attaching package: 㤼㸱ggcorrplot㤼㸲

The following object is masked from 㤼㸱package:rstatix㤼㸲:

    cor_pmat
ggcorrplot(cor.matrix)

From the correlation matrix we can confirm that almost all features negatively correlate to each other. An exception is the relationship between feature “Measuring steps” and “Exercise tracking”, which correlates positively. This matrix can be useful for digging deeper in relationship between preferences for features. For instance, we can assume that feature “Measuring steps” and “Exercise tracking” correlate positively because users see them as complementary features. Moreover, if we say that walking is a type of exercise (in case of longer walking routes), we can assume that users, who ranked “Exercise tracking” high, ranked “Measuring steps” high as well, because they perceive it as another type of “Exercise tracking”.

Constant Sum question

If you wish to obtain information about how much one attribute is preferred over another one, you may use a constant sum scale. The total box should always be displayed at the bottom to make it easier for respondents. A constant sum question permits collection of ratio data type. With data obtained we would be able to express the relative importance of the options.

Constant Sum Question
Location Price Ambience Customer Service id
32 23 32 13 1
25 30 22 23 2
19 21 30 30 3
20 20 20 40 4
30 30 10 30 5
0 20 20 60 6
# Compute descriptive statistics
library(pastecs) 

Attaching package: 㤼㸱pastecs㤼㸲

The following objects are masked from 㤼㸱package:dplyr㤼㸲:

    first, last
res <- stat.desc(constant.sum)
round(res[,1:4],2)
# Creation of the long version of data frame
constant.sum.long <-melt(constant.sum[,-5], variable.name ="Factor" ,value.name = "Points")
constant.sum.long
# Boxplot ggplot2
p<-constant.sum.long %>% 
  filter(Factor!="id") %>%
  ggplot(aes(x=Factor, y=Points, fill= Factor)) +
    geom_boxplot()  +
    theme_minimal() +
    ggtitle("What factors do you consider when choosing a place to go for a dinner?") +
    xlab("")
ggplotly(p)

With the data collected we are able to answer the question: what factor is the most important for our respondents when they go out for a dinner?

library(robCompositions)
Loading required package: pls

Attaching package: 㤼㸱pls㤼㸲

The following object is masked from 㤼㸱package:stats㤼㸲:

    loadings

Loading required package: data.table
data.table 1.13.0 using 2 threads (see ?getDTthreads).  Latest news: r-datatable.com

Attaching package: 㤼㸱data.table㤼㸲

The following objects are masked from 㤼㸱package:pastecs㤼㸲:

    first, last

The following objects are masked from 㤼㸱package:reshape2㤼㸲:

    dcast, melt

The following object is masked from 㤼㸱package:DescTools㤼㸲:

    %like%

The following objects are masked from 㤼㸱package:dplyr㤼㸲:

    between, first, last

Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2
sROC 0.1-2 loaded
constSum(constant.sum,100)[,-5]

In order to anwser this question we need to conduct a repeated measures ANOVA. This type of ANOVA is used for analyzing data where the same subjects are measured more than once. In our case we have every respondent measured on each of the factors (locations, price, ambience and customer service). Repeated measures ANOVA is an extension of the paired-samples t-test. This test is also referred to as a within-subjects ANOVA. In the within-subject experimental design the same individuals are measured on the same outcome variable under different time points or conditions.

We need to check all assumptions that need to be fulfilled in order to deploy this type of ANOVA. There are three assumputions that need to check. The first to check that each level of the independent variable is approximately normally distributed. Since we have more than 30 observations at each level, we do not need to proceed further due to the central limit theorem. Second assumption referrs to extreme outliers. Let’s have a look at potential outliers:

# Outliers
constant.sum.long %>% 
  group_by(Factor) %>%
  identify_outliers(Points)

As we cannot identify any extreme outliers, we can proceed with deploying repeated measures ANOVA.

# Formatting data 
constant.sum.aov <- gather(constant.sum, key = "Factor", value = "Points", ` Location`,` Price`,` Ambience`,` Customer Service`)
attributes are not identical across measure variables;
they will be dropped
# One-way repeated measures ANOVA  
res.aov <- anova_test(data = constant.sum.aov, dv = Points,wid = id ,within = Factor)
get_anova_table(res.aov)
ANOVA Table (type III tests)

  Effect  DFn    DFd      F        p p<.05   ges
1 Factor 2.56 297.36 33.668 1.06e-16     * 0.225
# Post hoc test
pairwise.t.test(constant.sum.long$Points,constant.sum.long$Factor, paired = T, p.adjust.method = "holm")

    Pairwise comparisons using paired t tests 

data:  constant.sum.long$Points and constant.sum.long$Factor 

                   Location  Price  Ambience
 Price            2.7e-15   -      -        
 Ambience         3.2e-10   0.030  -        
 Customer Service < 2e-16   0.742  0.079    

P value adjustment method: holm 

Now we can clearly see that our respondents consider price more than location, or ambience, while customer service is perceived almost equally important as prices.

ggstatsplot::ggwithinstats(
  data = constant.sum.long %>% filter(Factor!="id"), # excluding "id" column from the data
  x = Factor,
  y = Points,
  type = "p",
  pairwise.comparisons = TRUE, # show pairwise comparison test results
  title = "What factors do you consider when choosing a place to go for a dinner?")

Text or number entry question

A text or number entry question is a recommended type of question if you are interested in obtaining ratio data type. We will use this type of question together with a constant sum question type to collect data that can be analysed with regression analysis. Note that in this case we treat constant sum data as ratio data and therefore assume that 0 means complete absence.

Here is a glimpse in answers on how important is each factor to our respondents when it comes to dinning outside:

Constant sum question
Location Price Ambience Customer Service
32 23 32 1
25 30 22 43
19 21 30 34
20 20 20 46
30 30 10 17
0 20 20 4

Additionally, we asked our respondents how much are they willing to spend on dinner on average. In order to handle data easier, we will create a new data frame where we merge all the data together:

dinner <- subset(qualtrics, select = c(" Location"," Price"," Ambience"," Customer Service", " Willingness-to-pay (in EUR)"))
knitr::kable(head(dinner))
Location Price Ambience Customer Service Willingness-to-pay (in EUR)
32 23 32 1 29
25 30 22 43 77
19 21 30 34 52
20 20 20 46 31
30 30 10 17 22
0 20 20 4 35

Before we conduct a linear regression analysis, we need to take a look at correlation matrix:

correlation <-cor(dinner, method=c('pearson'))
correlation
                               Location       Price    Ambience
 Location                     1.0000000 -0.31732620 -0.36134355
 Price                       -0.3173262  1.00000000 -0.21962027
 Ambience                    -0.3613436 -0.21962027  1.00000000
 Customer Service            -0.1668810  0.08894752 -0.02405881
 Willingness-to-pay (in EUR)  0.1414540 -0.07438388 -0.32550607
                              Customer Service  Willingness-to-pay (in EUR)
 Location                          -0.16688104                   0.14145397
 Price                              0.08894752                  -0.07438388
 Ambience                          -0.02405881                  -0.32550607
 Customer Service                   1.00000000                   0.12125571
 Willingness-to-pay (in EUR)        0.12125571                   1.00000000

From our data we see, for instance, that some negative correlation between willingness to pay and importance of ambiance as well as some positive correlation between importance of customer service and willingness-to-pay. Let us observe descriptive statistics as well:

knitr::kable(psych::describe(dinner))
vars n mean sd median trimmed mad min max range skew kurtosis se
Location 1 117 12.14530 10.85823 10 11.25263 14.8260 0 40 40 0.3585257 -0.8903393 1.003844
Price 2 117 31.48718 16.22079 30 29.83158 14.8260 0 100 100 1.5662904 4.1917874 1.499613
Ambience 3 117 25.76068 13.97822 20 25.09474 14.8260 0 60 60 0.3807401 -0.3100357 1.292286
Customer Service 4 117 49.35897 29.47777 47 49.29474 40.0302 0 98 98 0.0342022 -1.1897398 2.725221
Willingness-to-pay (in EUR) 5 117 32.99145 26.26801 30 30.28421 29.6520 0 110 110 0.8007002 0.0124325 2.428479

We see that difference between mean and median does not suggest (at the first sight) great effect of outliers. Let us now do linear regression analysis:

mlr.dinner <- lm(` Willingness-to-pay (in EUR)` ~ ` Location` + ` Price` + ` Ambience`+` Customer Service`, data = dinner)
summary(mlr.dinner)

Call:
lm(formula = ` Willingness-to-pay (in EUR)` ~ ` Location` + ` Price` + 
    ` Ambience` + ` Customer Service`, data = dinner)

Residuals:
    Min      1Q  Median      3Q     Max 
-40.810 -18.205  -3.314  14.059  74.274 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)         55.31553   11.57393   4.779 5.38e-06 ***
` Location`         -0.06739    0.25556  -0.264 0.792503    
` Price`            -0.28455    0.16117  -1.765 0.080205 .  
` Ambience`         -0.69755    0.19088  -3.654 0.000394 ***
` Customer Service`  0.10988    0.07931   1.386 0.168646    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.72 on 112 degrees of freedom
Multiple R-squared:  0.1449,    Adjusted R-squared:  0.1144 
F-statistic: 4.745 on 4 and 112 DF,  p-value: 0.001421

Out of all factors of importance when dinning out, the only one that suggests significance at 0.05 level of significance is ambience. From the summary we can conclude that increase in importance of ambience by 1 point, leads to decrease in willingness to pay by -0.697554.

confint(mlr.dinner)
                          2.5 %      97.5 %
(Intercept)         32.38327198 78.24779707
` Location`         -0.57374787  0.43897062
` Price`            -0.60389395  0.03479312
` Ambience`         -1.07575993 -0.31934814
` Customer Service` -0.04725424  0.26701295

From confidence intervals, We can conclude that when we do not consider any of given factors (location, price, ambience and customer service), willingness to pay will be somewhere between 32.383272EUR and 78.2477971EUR. Besides that, for each increase in importance of dinner ambiance by one point, there will be an average decrease of willingness to pay between -1.0757599 and -0.3193481.

ggcoefstats(x = mlr.dinner,
            title = "Willingness to pay predicted by importance of factors")
New names:
* NA -> ...1
* NA -> ...2
* NA -> ...3
* NA -> ...4

There are couple of things we need to consider when we do multiple linear regression. One of them are potential outliers in our data. Here we identify and visualize them:

# Outliers
outlier_values <- boxplot.stats(mlr.dinner$residuals)$out  # outlier values.
outlier_values
      12       44       49 
70.56037 64.19796 74.27359 

We identified observations that belong to outlier values. We can even visualize them too:

boxplot(mlr.dinner$residuals, main="Willingnes to pay", boxwex=0.1)

In addition, we need to observe whether there are any influential observations:

plot(mlr.dinner,4)

A rule of thumb to determine whether an observation should be classified as influential or not is to look for observation with a Cook’s distance > 1 .We see from the graph that there are no influential observations.

Another thing to consider is linearity, i.e. that the relationship between the dependent and the independent variable can be reasonably approximated in linear terms:

# Linear specification
library(car)
Loading required package: carData

Attaching package: 㤼㸱car㤼㸲

The following object is masked from 㤼㸱package:DescTools㤼㸲:

    Recode

The following object is masked from 㤼㸱package:dplyr㤼㸲:

    recode
avPlots(mlr.dinner)

In our example it does not seem that linear relationships can be reasonably assumed for all variables.

As we already learned, another important assumption of the linear model is that the error terms have a constant variance (i.e., homoscedasticity):

# Breusch-Pagan Test
library(lmtest)
Loading required package: zoo

Attaching package: 㤼㸱zoo㤼㸲

The following objects are masked from 㤼㸱package:base㤼㸲:

    as.Date, as.Date.numeric
bptest(mlr.dinner)

    studentized Breusch-Pagan test

data:  mlr.dinner
BP = 1.1478, df = 4, p-value = 0.8866

The null hypothesis for this test is that the error variances are all equal, and our result is insignificant. Therefore, this assumption is met.

Another assumption to be met is that the error term is normally distributed. One way to check for normal distribution of the data is to employ statistical with the null hypothesis that the data is normally distributed. One of these is a Shapiro–Wilk test:

shapiro.test(resid(mlr.dinner))

    Shapiro-Wilk normality test

data:  resid(mlr.dinner)
W = 0.94757, p-value = 0.0001763

When the assumption of normally distributed errors is not met (as it is not met in our case), this might again be due to a misspecification of your model, in which case it might help to transform your data.

Finally, we need to check for multicollinearity, the case when there is a strong linear relationship between the independent variables:

correlation <-cor(dinner, method=c('pearson'))
correlation
                               Location       Price    Ambience
 Location                     1.0000000 -0.31732620 -0.36134355
 Price                       -0.3173262  1.00000000 -0.21962027
 Ambience                    -0.3613436 -0.21962027  1.00000000
 Customer Service            -0.1668810  0.08894752 -0.02405881
 Willingness-to-pay (in EUR)  0.1414540 -0.07438388 -0.32550607
                              Customer Service  Willingness-to-pay (in EUR)
 Location                          -0.16688104                   0.14145397
 Price                              0.08894752                  -0.07438388
 Ambience                          -0.02405881                  -0.32550607
 Customer Service                   1.00000000                   0.12125571
 Willingness-to-pay (in EUR)        0.12125571                   1.00000000

By observing our correlation matrix, we can see that non of the coefficients suggest values close to 0.8 or 0.9. Consequently, we conclude that there are no concerns regarding the multicolinearity between independent variables.

Reporting

inttor

Presentation guidelines & grading

Your performance in this part will be evaluated based on the following criteria:

Final presentation and submission

LS0tDQpvdXRwdXQ6DQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgdHlwZT0idGV4dC9jc3MiIG1lZGlhPSJhbGwiIGhyZWY9InN0eWxlLmNzcyIgLz4NCg0KYGBge3IsIGluY2x1ZGU9RkFMU0UsIGZpZy5jYXA9IkEgc3RydWN0dXJlIG9mIHRoZSBncm91cCBwcm9qZWN0In0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXJyb3IgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpDQpgYGANCg0KIyAoUEFSVCkgR3JvdXAgcHJvamVjdCB7LX0NCg0KIyBJbnRybyB7LX0NCg0KV2VsY29tZSB0byB0aGUgaW50cm9kdWN0aW9uIHRvIHRoZSBncm91cCBwcm9qZWN0IQ0KDQo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCg0KSGVyZSB5b3Ugd2lsbCBmaW5kIGFsbCBpbXBvcnRhbnQgcG9pbnRzIHJlbGF0ZWQgdG8gdGhlIGdyb3VwIHByb2plY3QuIEluIHRoZSBmb2xsb3dpbmcgc3ViY2hhcHRlcnMsIHlvdSBjYW4gZmluZCBleHBsYW5hdGlvbnMgZm9yIGVhY2ggc3RlcCB5b3Ugc2hvdWxkIHRha2UgaW4geW91ciBncm91cCBwcm9qZWN0LiBHZW5lcmFsbHksIHRoZSBncm91cCBwcm9qZWN0IGNvbXByaXNlcyB0d28gcGFydHMuIEluIHRoZSBmaXJzdCBwYXJ0LCB5b3Ugd2lsbCB3b3JrIHdpdGggeW91ciBncm91cCBvbiBjcmVhdGluZyBhbmQgY29uZHVjdGluZyBhIHN1cnZleS4gT25jZSB5b3UgaGF2ZSBjcmVhdGVkIGEgZHJhZnQgb2YgeW91ciBxdWVzdGlvbm5haXJlLCB5b3Ugd2lsbCByZWNlaXZlIGEgZmVlZGJhY2sgZnJvbSB1cy4gQWZ0ZXIgaW1wbGVtZW50aW5nIHRoZSBmZWVkYmFjaywgeW91IHdpbGwgYmUgcmVhZHkgdG8gc3RhcnQgY29sbGVjdGluZyBkYXRhISBJbiB0aGUgc2Vjb25kIHBhcnQsIHlvdSB3aWxsIGhhdmUgYSBjaGFuY2UgdG8gYXBwbHkgc3RhdGlzdGljYWwga25vd2xlZGdlIGFjcXVpcmVkIGluIHRoZSBjbGFzcyBhbmQgZnJvbSBvbmxpbmUgc2NyaXB0LiBJbiBmYWN0LCB5b3Ugd2lsbCBhbmFseXplIHRoZSBjb2xsZWN0ZWQgZGF0YSwgcHJlc2VudCB5b3VyIGZpbmRpbmdzIGFuZCBmaW5hbGx5IHN1Ym1pdCB5b3VyIGZpbmFsIHJlcG9ydCAoUiBjb2RlIGFuZCBwcmVzZW50YXRpb24pLg0KDQo8L2Rpdj4NCg0KDQpgYGB7cixlY2hvPUZBTFNFLG91dC53aWR0aCA9ICc3MCUnLGZpZy5hbGlnbj0nY2VudGVyJyxmaWcuY2FwPSJTdHJ1Y3R1cmUgb2YgdGhlIGdyb3VwIHByb2plY3QifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy9ncm91cF9wcm9qZWN0LlBORyIpDQpgYGANCg0KIyMgR3JvdXBzIHstfQ0KDQojIyBUb3BpY3MgZm9yIHRoZSBncm91cCBwcm9qZWN0IHstfQ0KDQpgYGB7ciBldmFsID0gVFJVRSwgZWNobyA9IEZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KbXl0YWJsZV9zdWIgPSBkYXRhLmZyYW1lKA0KICAgIFRvcGljID0gYygiQ2FyLXNoYXJpbmcgdnMuIHZlaGljbGUgb3duZXJzaGlwIiwNCiAgICAgICAgICAgICAiU3R1ZGVudCBjYW50ZWVuIChNZW5zYSkgYW5kIHRoZSBXVSBjYW1wdXMqIiwNCiAgICAgICAgICAgICAiUHJpdmFjeSBhbmQgc2VjdXJpdHkgaW4gc29jaWFsIG1lZGlhIiwNCiAgICAgICAgICAgICAiQ29uc3VtZXIgcHJlZmVyZW5jZXMgZm9yIGZhaXItdHJhZGUgcHJvZHVjdHMgaW4gdGhlIGFwcGFyZWwgaW5kdXN0cnkiLA0KICAgICAgICAgICAgICJUaGUgY2xpbWF0ZSBkZWJhdGUgYW5kIGdyZWVuIGNvbnN1bXB0aW9uIiwNCiAgICAgICAgICAgICAiU2VsZi1kcml2aW5nIGNhcnMiLA0KICAgICAgICAgICAgICJGcmVlbWl1bSBidXNpbmVzc21vZGVscyBpbiB0aGUgbXVzaWMgaW5kdXN0cnkiLA0KICAgICAgICAgICAgICJDb25zdW1lcnPigJkgYXR0aXR1ZGUgdG93YXJkcyBsZWdhbCB2aWRlbyBzdHJlYW1pbmcgcHJvdmlkZXJzIGFuZCBwaXJhY3kiLA0KICAgICAgICAgICAgICJJbXBhY3Qgb2YgQ29yb25hdmlydXMgb24gb25saW5lIHNob3BwaW5nIHNlcnZpY2VzIiwNCiAgICAgICAgICAgICAiSW1wbGljYXRpb25zIG9mIENvcm9uYXZpcnVzIG9uIGJyYW5kIGxveWFsdHkiLA0KICAgICAgICAgICAgICJDb25zdW1lcnPigJkgd2lsbGluZ25lc3MgdG8gcGF5IGZvciBvcmdhbmljIHByb2R1Y3RzIiwNCiAgICAgICAgICAgICAiVGhlIG1vc3QgbGl2ZWFibGVjaXR5IGluIHRoZSB3b3JsZCIsDQogICAgICAgICAgICAgIkRlc2lnbiB5b3VyIG93biBxdWVzdGlvbm5haXJlIG9uIGEgdG9waWMgb2YgeW91ciBjaG9pY2UiDQogICAgICAgICAgICAgKSwNCiAgICBEZXNjcmlwdGlvbiA9IGMoDQogICAgICAiRGV2ZWxvcCBhIHF1ZXN0aW9ubmFpcmUgdG8gZXhwbG9yZSB0aGUgYXR0cmFjdGl2ZW5lc3Mgb2YgY2FyIHNoYXJpbmcgb3B0aW9ucyBmb3IgY29uc3VtZXJzIChlLmcuLCBDYXIyZ28pLiBBcmUgY29uc3VtZXJzIHdpbGxpbmcgYW5kIHBsYW5uaW5nIHRvIHN1YnN0aXR1dGUgYSBwZXJzb25hbCB2ZWhpY2xlIHRocm91Z2ggY2FyIHNoYXJpbmcgb3B0aW9uPyBJcyBjYXIgc2hhcmluZyBsaWtlbHkgdG8gYWZmZWN0IHRoZSBhbW91bnQgb2YgZHJpdmluZz8gV2hpY2ggZmFjdG9ycyBpbmZsdWVuY2UgdGhlc2UgZGVjaXNpb25zPyIsDQogICAgICAiRGV2ZWxvcCBhIHF1ZXN0aW9ubmFpcmUgdG8gbWVhc3VyZSBzdHVkZW50c+KAmCBhdHRpdHVkZXMgYW5kIGl0cyBkcml2ZXJzIChlLmcuLCBxdWFsaXR5IG9mIG1lYWxzLCBwcmljZSwgZXRjLikgdG93YXJkIHRoZSBjYW50ZWVuIGFuZCBvdGhlciByZXN0YXVyYW50c29uIHRoZSBjYW1wdXMuIiwNCiAgICAgICJEZXZlbG9wIGEgcXVlc3Rpb25uYWlyZSB0byBtZWFzdXJlIGNvbnN1bWVyc+KAmSB3aWxsaW5nbmVzcyB0byBzd2l0Y2ggZnJvbSBXaGF0c0FwcCB0byBhIHNlY3VyZSBtZXNzYWdpbmcgc2VydmljZSAoZS5nLiwgVGhyZWVtYSkuIFdoYXQgYXJlIHRoZSBtYWluIG1vdGl2ZXMgKGUuZy4sIHNlY3VyaXR5IGNvbmNlcm5zLCBjb3N0cywgdXNhYmlsaXR5LCBldGMuKSwgYW5kIGFyZSBjb25zdW1lcnMgd2lsbGluZyB0byBwYXkgZm9yIHRoZSBzZWN1cmUgc2VydmljZSBwcm92aWRlcj8iLA0KICAgICAgIkRldmVsb3AgYSBxdWVzdGlvbm5haXJlIHRvIG1lYXN1cmUgY29uc3VtZXJz4oCZIHByZWZlcmVuY2VzIGZvciBzdXN0YWluYWJsZSBicmFuZHMgYW5kIGVjbyBmYXNoaW9uLiBDb25kdWN0IGFuIGV4cGVyaW1lbnQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdGhlcmUgYXJlIGRpZmZlcmVudCBwZXJjZXB0aW9ucyByZWdhcmRpbmcgdGhlIOKAnEZhaXIgVHJhZGXigJ0gZWZmZWN0LiIsDQogICAgICAiVGhlIGNsaW1hdGUgZGViYXRlIGlzIGN1cnJlbnRseSBvbiB0aGUgdG9wIG9mIHRoZSBhZ2VuZGEgb2YgbWFueSBuZXdzIG91dGxldHMuIFNvbWUgcHVibGljIGZpZ3VyZXMgdGhhdCBzdHJvbmdseSBmYXZvciBvbmUgc2lkZSBkb21pbmF0ZSBhbmQgZW1vdGlvbmFsaXplIHRoZSBkZWJhdGUgKGUuZy4sIEdyZXRhIFRodW5iZXJnLCBEb25hbGRUcnVtcCkuIEV4cGxvcmUgaW4gaG93IGZhciBjb25zdW1lcnMgYXJlIHdpbGxpbmcgdG8gY2hhbmdlIHRoZWlyIGJlaGF2aW9yIChlLmcuLGN1dCBhaXItdHJhdmVsKSB0byBoZWxwIHByb3RlY3QgdGhlIGVudmlyb25tZW50LiBXaGF0IGZhY3RvcnMgaW5mbHVlbmNlIHRoZSB3aWxsaW5nbmVzcyB0byBjaGFuZ2UgKGUuZy4sIHNvY2lhbCBmYWN0b3JzLCBjb252ZW5pZW5jZSk/IiwNCiAgICAgICJDb21wYW5pZXMgc3VjaCBhcyBHb29nbGUgaGVhdmlseSBpbnZlc3QgaW4gdGhlIGRldmVsb3BtZW50IG9mIHNlbGYtZHJpdmluZyBjYXJzLiBEZXZlbG9wIGEgcXVlc3Rpb25uYWlyZSB0byBtZWFzdXJlIGNvbnN1bWVycyBhdHRpdHVkZSBhbmQgdXNhZ2UgaW50ZW50aW9uIGZvciBzZWxmLWRyaXZpbmcgY2Fycy4gV2hhdCBhcmUgdGhlIGRyaXZlcnMgYW5kIGRldGVycmVudHMgb2YgdGhlIGNvbnN1bWVyc+KAmSB3aWxsaW5nbmVzcyB0byBhZG9wdCB0aGlzIGlubm92YXRpb24/IiwNCiAgICAgICJNYW55IG11c2ljIHN0cmVhbWluZyBzZXJ2aWNlcyAoZS5nLiwgU3BvdGlmeSkgb2ZmZXIgYSBiYXNlbGluZSB2ZXJzaW9uIGZyZWUgb2YgY2hhcmdlIHRvIGNvbnN1bWVycyBidXQgY2hhcmdlIGZvciBhIHByZW1pdW0gdmVyc2lvbiB3aXRoIGFkZGl0aW9uYWwgZmVhdHVyZXMuIERldmVsb3AgYSBxdWVzdGlvbm5haXJlIHRvIG1lYXN1cmUgY29uc3VtZXJz4oCZIGF0dGl0dWRlIHRvd2FyZHMgbGVnYWwgbXVzaWMgc3RyZWFtaW5nIHByb3ZpZGVycy5XaGF0IGZhY3RvcnMgaW5mbHVlbmNlIHRoZSBhdHRpdHVkZShlLmcuLCBvY2N1cGF0aW9uLCBnZW5kZXIsIHVzYWdlIGJlaGF2aW9yIGV0Yy4pLCBhbmQgaG93IGNvdWxkIGNvbXBhbmllcyBtb3RpdmF0ZSBjb25zdW1lcnMgdG8gY29udmVydHRvIHRoZSBwcmVtaXVtIHZlcnNpb24gb2YgdGhlIHNlcnZpY2U/IiwNCiAgICAgICJWaWRlbyBzdHJlYW1pbmcgcHJvdmlkZXJzIGxpa2UgTmV0ZmxpeCByZWNvcmQgYSBjb250aW51b3VzIGluY3JlYXNlIGluIHJlZ2lzdGVyZWQgdXNlcnMuIE9uIHRoZSBvdGhlciBoYW5kLCBpbGxlZ2FsIHZpZGVvIHN0cmVhbWluZyBwb3J0YWxzIChlLmcuLCBQb3Bjb3JuIFRpbWUpIGFyZSBoZWF2aWx5IHVzZWQgYnkgb3RoZXIgY29uc3VtZXJzLiBEZXZlbG9wIGEgcXVlc3Rpb25uYWlyZSB0byBtZWFzdXJlIGNvbnN1bWVyc+KAmSBhdHRpdHVkZSBhbmQgZHJpdmVycyAoZS5nLiBvY2N1cGF0aW9uLCBnZW5kZXIsIHVzYWdlIGJlaGF2aW9yIGV0Yy4pIHRvd2FyZHMgbGVnYWwgdmlkZW8gc3RyZWFtaW5nIHByb3ZpZGVycy4gV2hhdCBjb3VsZCBiZSByZWFzb25zIGZvciBwaXJhY3k/IiwNCiAgICAgICJNb3JlIGFuZCBtb3JlIHBlb3BsZSB1c2Ugb25saW5lIHNob3BwaW5nIHNlcnZpY2VzIChlLmcuLCBBbWF6b24gRnJlc2gsIEJpbGxhT25saW5lKSB0byBidXkgZ3JvY2VyaWVzIHNpbmNlIENvcm9uYXZpcnVzIHN0YXJ0ZWQgc3ByZWFkaW5nLiBEZXZlbG9wIGEgcXVlc3Rpb25uYWlyZSB0byBtZWFzdXJlIGNvbnN1bWVyc+KAmSBhdHRpdHVkZSBhbmQgaXRzIGRyaXZlcnMgKGUuZy4sIHByaWNlLCBzZXJ2aWNlKSB0b3dhcmRzIHRoZSBvbmxpbmUgc2VydmljZXMgZHVyaW5nIGFuZCBiZWZvcmUgQ29yb25hdmlydXMgb3V0YnJlYWsuIEFyZSBjb25zdW1lcnMgbGVzcyBwcmljZSBzZW5zaXRpdmUgd2hlbiBzaG9wcGluZyBvbmxpbmUgdGhhbiBpbiB0aGUgb2ZmbGluZSBzdG9yZXM/IEhvdyBsaWtlbHkgYXJlIGNvbnN1bWVycyB0byBjb250aW51ZSB1c2luZyBvbmxpbmUgc2hvcHBpbmcgc2VydmljZXMgaW4gdGhlIGZ1dHVyZT8iLA0KICAgICAgIkFmdGVyIG91dGJyZWFrIG9mIENvcm9uYXZpcnVzIG1hbnkgY29uc3VtZXJzIHN0cmF5ZWQgZnJvbSBub3JtYWwgc2hvcHBpbmcgcGF0dGVybnMgYW5kIGJlZ2FuIHN0b2NrcGlsaW5nIHByb2R1Y3RzLiBNYW55IHJldGFpbGVycyB3ZXJlIHdvcmtpbmcgYXJvdW5kIHRoZSBjbG9jayB3aXRoIHRoZWlyIHNlbGxpbmcgcGFydG5lcnMgdG8gZW5zdXJlIGF2YWlsYWJpbGl0eSBvbiBhbGwgb2Ygb3VyIHByb2R1Y3RzLCBhbmQgYnJpbmcgb24gYWRkaXRpb25hbCBjYXBhY2l0eS4gSG93IGRpZCBpdCBhZmZlY3QgYnJhbmQgbG95YWx0eT8gRGlkIGNvbnN1bWVycyB0cnkgb3V0IGFsdGVybmF0aXZlIGJyYW5kcz8gSWYgc28sIGJ5IHdoYXQgZmFjdG9ycyB3ZXJlIGNvbnN1bWVycyBkcml2ZW4gdG8gY2hhbmdlIHRoZSBicmFuZCB0aGV5IHVzZWQgYmVmb3JlPyIsDQogICAgICAiRGV2ZWxvcCBhIHF1ZXN0aW9ubmFpcmUgdG8gbWVhc3VyZSBjb25zdW1lcnPigJkgd2lsbGluZ25lc3MgdG8gcGF5IGZvciBvcmdhbmljIHByb2R1Y3RzIChlLmcuLCBtaWxrKS4gSG93IG11Y2ggYXJlIGNvbnN1bWVycyB3aWxsaW5nIHRvIHBheSBmb3Igb3JnYW5pYyBtaWxrIHZzLiBjb252ZW50aW9uYWwgbWlsaz8gV2hhdCBpcyB0aGUgb2JzZXJ2ZWQgcHJpY2UgcHJlbWl1bT8gSG93IGRvZXMgdGhpcyB2YXJ5IGFjcm9zcyBjb25zdW1lcnM/IFdoYXQgYXJlIHRoZSBkcml2ZXJzPyBEb2VzIGl0IHJlZmxlY3QgYSBkZXNpcmUgdG8gYWNoaWV2ZSBiZXR0ZXIgaGVhbHRoLCBlYXQgYmV0dGVyIHF1YWxpdHkgZm9vZCwgb3IgdG8gY29udHJpYnV0ZSB0byBlbnZpcm9ubWVudGFsIHByb3RlY3Rpb24/IiwNCiAgICAgICJWaWVubmEgaXMgZnJlcXVlbnRseSBsaXN0ZWQgYXMgb25lIG9mIHRoZSBtb3N0IGxpdmVhYmxlY2l0aWVzIGluIHRoZSB3b3JsZCAoZS5nLiwgYnkgdGhlIEVjb25vbWlzdCBJbnRlbGxpZ2VuY2UgVW5pdCkuIERldmVsb3AgYSBxdWVzdGlvbm5haXJlIHRvIGludmVzdGlnYXRlIHRoZSByZWFzb25zIHdoeSBWaWVubmEgcmFua3NzbyBoaWdoIGluIGRpZmZlcmVudCByYW5raW5ncy4gV2hhdCBhcmUgdGhlIGZhY3RvcnMgdGhhdCBjb250cmlidXRlIHRvIGl0cyBpbWFnZT8gQXJlIHRoZXJlIGRpZmZlcmVuY2VzIGJldHdlZW4gZGlmZmVyZW50IGdyb3VwcyBvZiBwZW9wbGU/IiwNCiAgICAgICJGZWVsIGZyZWUgdG8gY2hvb3NlIHRvcGljIG9mIHlvdXIgY2hvaWNlIGFzIHdlbGwuIg0KICAgICkpDQoNCm15dGFibGVfc3ViICU+JSBrYWJsZShlc2NhcGUgPSBUKSAlPiUNCiAga2FibGVfcGFwZXIoYygiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYpDQoNCmBgYA0KDQoNCiMgUGFydCAxOiBCZWZvcmUgY29sbGVjdGluZyBkYXRhIHstfQ0KDQo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4NCg0KQW4gYWltIG9mIHRoaXMgY291cnNlIGlzIHRvIGRldmVsb3AgeW91ciBhYmlsaXR5IHRvIHRyYW5zbGF0ZSBidXNpbmVzcyBwcm9ibGVtcyBpbnRvIGFjdGlvbmFibGUgcmVzZWFyY2ggcXVlc3Rpb25zIGFuZCB0byBkZXNpZ24gYW4gYWRlcXVhdGUgcmVzZWFyY2ggcGxhbiB0byBhbnN3ZXIgdGhlc2UgcXVlc3Rpb25zLiBUaGVyZWZvcmUsIHlvdSBuZWVkIHRvIGJlIGVxdWlwZWQgd2l0aCBrbm93bGVkZ2Ugb24gaG93IHRvIGNyZWF0ZSBhIHN1cnZleSBhbmQgcHJvcGVybHkgY29uZHVjdCBhIHJlc2VhcmNoLiANCg0KR2VuZXJhbGx5LCB3aGF0IHlvdSBjYW4gZXhwZWN0IGZyb20gdGhlIHN1cnZleSBkZXNpZ24gaXMgc2ltaWxhciB0byB3aGF0IG9uZSBleHBlcmllbmNlcyBpbiBhIHJlbGF0aW9uc2hpcC4gSWYgeW91IHRyeSB0byB0YWtlIG1vcmUgdGhhbiB5b3UgY29tbWl0LCBpdCBkb2VzbuKAmXQgd29yayBvdXQuIE5vdyBvbiBhIHNlcmlvdXMgbm90ZSwgaWYgeW91IGZvbGxvdyBndWlkZWxpbmVzIG1lbnRpb25lZCBoZXJlLCB5b3Ugd2lsbCBjZXJ0YWlubHkgYXZvaWQgdXN1YWwgdHJhcHMgeW91ciBmZWxsb3cgY29sbGVndWVzIHdlcmUgY2F1Z2h0IGluLg0KDQpJbiBhIHJlc2VhcmNoIHByb2Nlc3MsIGNvbmR1Y3RpbmcgYSBzdXJ2ZXkgaXMgYSBwYXJ0IG9mIChwcmltYXJ5KSBkYXRhIGNvbGxlY3Rpb24uIEJlZm9yZSB3ZSBjb2xsZWN0IGRhdGEsIHdlIGhhdmUgdG8gbWFrZSBzdXJlIHRoYXQgcHJlY2VkaW5nIHN0ZXBzIGFyZSBjb3JyZWN0bHkgZG9uZS4gSG93ZXZlciwgaW4gdGhlIGZvbGxvd2luZyBzZWN0aW9ucyB3ZSB3aWxsIGZvY3VzIG9uIHRoZSBwcm9jZXNzIG9mIGRlc2lnbmluZyBhIHF1ZXN0aW9ubmFpcmUuIEV2ZW50dWFsbHksIHlvdSB3aWxsIGJlIGFibGUgdG8gY29sbGVjdCByZWxldmFudCBkYXRhIGFuZCBhcHBseSBhcHByb3ByaWF0ZSBzdGF0aXN0aWNhbCB0ZXN0cy4gICAgDQoNCjwvZGl2Pg0KDQoNCmBgYHtyLGVjaG89RkFMU0Usb3V0LndpZHRoID0gJzcwJScsZmlnLmFsaWduPSdjZW50ZXInfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoInJlc2VhcmNoLXByb2Nlc3MuUE5HIikNCmBgYA0KDQo6Ojogey5pbmZvYm94X3JlZCAuY2F1dGlvbiBkYXRhLWxhdGV4PSJ7Y2F1dGlvbn0ifQ0KTm90ZSB0aGF0IHRoaXMgYXNzaWdubWVudCBtYXkgcmVxdWlyZSB5b3UgdG8gZGVhbCB3aXRoIGFuZCBpbnRlZ3JhdGUNCmtub3dsZWRnZSB0aGF0IGhhcyBub3QgeWV0IGJlZW4gY292ZXJlZCBpbiBjbGFzcyEgU3R1ZGVudHMgYXJlDQpleHBlY3RlZCB0byByZWFkIGFoZWFkIGFuZCBjb2xsZWN0IGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gdG8gdGhlDQpleHRlbnQgdG8gd2hpY2ggdGhlaXIgcHJvamVjdCByZXF1aXJlcyB0aGlzLg0KOjo6DQoNCg0KIyMgUmVzZWFyY2ggZGVzaWduDQoNCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGp1c3RpZnkiPg0KDQpBcyB5b3UgYWltIHRvIGNvbmR1Y3QgYSByZWFsIG1hcmtldGluZyByZXNlYXJjaCwgYmVmb3JlIHlvdSBzdGFydCB3cml0aW5nIGRvd24gcXVlc3Rpb25zIGZvciBhIHF1ZXN0aW9ubmFpcmUsIHlvdSBuZWVkIHRvIGNvbWUgdXAgd2l0aCBhIHJlc2VhcmNoIGRlc2lnbi4gSW4gcGFydGljdWxhciwgeW91IHNob3VsZCByZXZpZXcgdGhlIHJlc2VhcmNoIHF1ZXN0aW9ucywgaHlwb3RoZXNlcyBhbmQgY2hhcmFjdGVyaXN0aWNzIHRoYXQgaW5mbHVlbmNlIHRoZSByZXNlYXJjaCBkZXNpZ24uICANCg0KSWYgeW91IGFyZSBpbnRlcmVzdGVkIGluIHRoZSBjYXVzYWwgZWZmZWN0IG9mIG9uZSBwYXJ0aWN1bGFyIChpbmRlcGVuZGVudCkgdmFyaWFibGUgb24gYW5vdGhlciAoZGVwZW5kZW50KSB2YXJpYWJsZSwgdGhpbmsgYWJvdXQgYW4gZXhwZXJpbWVudGFsIGRlc2lnbiB0aGF0IG1pZ2h0IGFsbG93IHlvdSB0byBtYW5pcHVsYXRlIHRoaXMgdmFyaWFibGUuIEluIHRoaXMgY2FzZSwgeW91IHBhcnRpY3VsYXJseSBoYXZlIHRvIGRlY2lkZSBvbiB0aGUgZm9sbG93aW5nOiAgDQoNCiogV2hpY2ggdmFyaWFibGUgdG8gbWFuaXB1bGF0ZT8gIA0KKiBXaGV0aGVyIHRvIHVzZSBhIGJldHdlZW4tc3ViamVjdHMgb3Igd2l0aGluLXN1YmplY3RzIGRlc2lnbj8gIA0KKiBUaGUgY2F1c2UtZWZmZWN0IHNlcXVlbmNlICh0aGUgY2F1c2UgbXVzdCBvY2N1ciBiZWZvcmUgdGhlIGVmZmVjdCkgIA0KKiBUaGUgbnVtYmVyIG9mIGV4cGVyaW1lbnRhbCBjb25kaXRpb25zICANCiogUG90ZW50aWFsIGludGVyYWN0aW9ucyBhbmQgcmVsYXRpb25zaGlwcyB3aXRoIG90aGVyIHZhcmlhYmxlcyAoZG9lcyB0aGUgZWZmZWN0IGRlcGVuZCBvbiBhbm90aGVyIHZhcmlhYmxlPykNCg0KV2hhdCB5b3UgbmVlZCB0byBiZSBjYXJlZnVsIGFib3V0IGlzIHRoZSBlZmZlY3Qgb2YgKipyZXZlcnNlZCBjYXVzYXRpb24qKi4gVGhlIGVmZmVjdCByZWZlcnMgdG8gdGhlIHNpdHVhdGlvbiB3aGVyZSB0aGUgY2F1c2FsIHJlbGF0aW9uc2hpcCBjb3VsZCBwb3NzaWJsZSBoYXZlIGFuIG9wcG9zaXRlIGRpcmVjdGlvbiBmcm9tIHdoYXQgd2UgYXNzdW1lZCBhdCB0aGUgZmlyc3QgcGxhY2UuIEZvciBpbnN0YW5jZSwgaXQgaXMgb2Z0ZW4gYXNzdW1lZCB0aGF0IGFuIGluY3JlYXNlIGluIGluZGl2aWR1YWwgaW5jb21lIGxlYWRzIHRvIGluY3JlYXNlIGluIHdlbGwtYmVpbmcgKGhhcHBpbmVzcykuIEhvd2V2ZXIsIHNvbWUgW3Jlc2VhcmNoZXNdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzE2OTQ5NjkyKSBzdWdnZXN0IHRoYXQgdGhpcyBjYXVzYXRpb24gY291bGQgaGF2ZSBhbiBvcHBvc2l0ZSBkaXJlY3Rpb24sIGkuZS4gdGhhdCBhY3R1YWxseSBpbmNyZWFzZSBpbiB3ZWxsLWJlaW5nIG9mIGFuIGluZGl2aWR1YWwgbGVhZHMgdG8gYW4gaW5jcmVhc2UgaW4gaW5jb21lLiAgDQoNCkhlcmUgYXJlIHNvbWUgZXhhbXBsZXMgb2YgY2F1c2FsIHJlc2VhcmNoIGRlc2lnbiBhcHBsaWNhdGlvbnM6ICANCg0KKiBUbyBhc3Nlc3MgaG93IGEgcHJvZHVjdCdzIGNvdW50cnktb2Ytb3JpZ2luIGltcGFjdHMgYXR0cmFjdGl2ZW5lc3MgYWNyb3NzIGRpZmZlcmVudCBjb3VudHJpZXMuICANCiogVG8gYW5hbHlzZSB0aGUgZWZmZWN0cyBvZiByZWJyYW5kaW5nIG9uIGN1c3RvbWVyIGxveWFsdHkuICANCg0KYGBge3IsZWNobz1GQUxTRSwgb3V0LndpZHRoID0gJzcwJScsZmlnLmFsaWduPSdjZW50ZXInfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImNhdXNhdGlvbi1lZmZlY3QucG5nIikNCmBgYA0KDQoNCklmIHlvdSB3b3VsZCBsaWtlIHRvIGFuYWx5emUgdGhlIGVmZmVjdHMgb2YgbXVsdGlwbGUgY2F0ZWdvcmljYWwgb3IgY29udGludW91cyAoaW5kZXBlbmRlbnQpIHZhcmlhYmxlcyBvbiBvbmUgY29udGludW91cyAoZGVwZW5kZW50KSB2YXJpYWJsZSwgeW91IG1pZ2h0IHVzZSBhIHJlZ3Jlc3Npb24gbW9kZWwuIFdoZW4gZG9pbmcgdGhpcywgeW91IHBhcnRpY3VsYXJseSBoYXZlIHRvIGRlY2lkZSBvbjogIA0KDQoqIEhvdyB0byBtZWFzdXJlICoqdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoRFYpKiouIFRoaXMgaXMgcGFydGljdWxhcmx5IGltcG9ydGFudCwgc2luY2UgeW91IG5lZWQgYSB2YXJpYWJsZSB0aGF0IGlzIHBvd2VyZnVsIGluIHVuY292ZXJpbmcgdmFyaWF0aW9uIGJldHdlZW4gc3ViamVjdHMgKGUuZy4sIG9wZW4tZW5kZWQgcXVlc3Rpb25zLCBzdWNoIGFzICJIb3cgbXVjaCBhcmUgeW91IHdpbGxpbmcgdG8gcGF5IGZvciB0aGlzIHByb2R1Y3QiIGFyZSBnb29kIGNhbmRpZGF0ZXMpLiBNb3Jlb3ZlciwgeW91IGFsc28gbmVlZCB0byBjb25zaWRlciB0aGUgbmF0dXJlIG9mIHlvdXIgRFYsaS5lLiB3aGV0aGVyIGl0IGlzIGFuIGludGVydmFsIHZhcmlhYmxlLCBvcmRpbmFsIG9yIGNhdGVnb3JpY2FsIHZhcmlhYmxlLiBUaGUgbmF0dXJlIG9mIHlvdXIgRFYgd2lsbCBoZWF2aWx5IGluZmx1ZW5jZSB5b3VyIGNob2ljZSBvZiBhIGNvcnJlY3Qgc3RhdGlzdGljYWwgdGVzdC4NCg0KKiBIb3cgdG8gbWVhc3VyZSAqKnRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgKElWKSoqIChzaW5nbGUtaXRlbSB2cy4gbXVsdGktaXRlbSBzY2FsZXMsIGNhdGVnb3JpY2FsIHZzLiBjb250aW51b3VzKS4gQmVhciBpbiBtaW5kIHRoYXQgdGhlIG5hdHVyZSBvZiB0aGUgSVYsIHRvZ2V0aGVyIHdpdGggRFYsIGFmZmVjdHMgeW91ciBjaG9pY2Ugb2YgYSBzdGF0aXN0aWNhbCB0ZXN0IGFzIHdlbGwuICANCg0KKiBXaGF0IG90aGVyIHZhcmlhYmxlcyBtaWdodCBjYXVzZSB0aGUgZWZmZWN0IHRoYXQgeW91IHdvdWxkIGxpa2UgdG8gaW52ZXN0aWdhdGUgKHRvIHByZXZlbnQgb21pdHRlZCB2YXJpYWJsZSBiaWFzLCBpLmUuIHZhcmlhYmxlcyB0aGF0IGFyZSBub3QgcGFydCBvZiB5b3VyIG1vZGVsIGJ1dCBzdGlsbCBpbmZsdWVuY2UgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSkuDQoNCiogUG90ZW50aWFsIGludGVyYWN0aW9ucyAoZS5nLiwgaXMgdGhlIGVmZmVjdCBvZiB2YXJpYWJsZSBYIHN0cm9uZ2VyIGZvciBncm91cCBBIHZzLiBCPykNCg0KPC9kaXY+DQoNCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aCA9ICc3MCUnLGZpZy5hbGlnbj0nY2VudGVyJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJtbHAtcmVncmVzc2lvbi5wbmciKQ0KYGBgDQoNCiMjIFN1cnZleSBtZXRob2QgIA0KDQpJbiB0aGUgbmV4dCBzdGVwIHlvdSBzaG91bGQgcmV2aWV3IHRoZSB0eXBlIG9mIHN1cnZleSBtZXRob2QgeW91IHdpbGwgdXNlLg0KDQpBdCB0aGlzIHBvaW50IHlvdSBuZWVkIHRvIHRoaW5rIGluIHdoaWNoIHNldHRpbmcgeW91IGFpbSB0byBjb25kdWN0IHlvdXIgc3VydmV5LiBGb3IgaW5zdGFuY2UsIHNob3VsZCB5b3UgZG8gaXQgaW4gYSBmYWNlLXRvLWZhY2Ugc2V0dGluZyBvciByYXRoZXIgb25saW5lLiBIZXJlIHlvdSBjYW4gZmluZCBzb21lIGFkdmFudGFnZXMgYW5kIGRpc2FkdmFudGFnZXMgb2Ygb25saW5lIHN1cnZleXM6DQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzUwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiYWR2LWRpc2Fkdi1vbmxpbmUtcXVlc3Rpb25uYWlyZS5wbmciKQ0KYGBgDQoNCkhlcmUgaXMgdGhlIGxpc3Qgb2YgdGhlIG9ubGluZSB0b29scyB5b3UgY2FuIHVzZSB0byBjb25kdWN0IGFuIG9ubGluZSBzdXJ2ZXkgKHVzdWFsbHkgZm9yIGZyZWUpOiAgDQoNCi0gW1F1YWx0cmljc10oaHR0cDovL3d3dy5xdWFsdHJpY3MuY29tL2ZyZWUtYWNjb3VudC8pDQotIFtHb29nbGUgZm9ybV0oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9mb3Jtcy9hYm91dC8pDQotIFtTdXJ2ZXkgbW9ua2V5XShodHRwczovL3d3dy5zdXJ2ZXltb25rZXkuY29tLykNCi0gW0ZyZWUgb25saW5lIHN1cnZlcnlzXShodHRwOi8vZnJlZW9ubGluZXN1cnZleXMuY29tLykNCi0gW0t3aWsgc3VydmV5c10oaHR0cDovL2t3aWtzdXJ2ZXlzLmNvbS8pDQoNCkZvciB0aGUgcHVycG9zZSBvZiB0aGlzIGNvdXJzZSwgd2Ugc3VnZ2VzdCB0byB1c2UgKipRdWFsdHJpY3MqKi4NCg0KQSBxdWVzdGlvbm5haXJlIGNyZWF0aW9uIGluIFF1YWx0cmljcyBzdGFydHMgd2l0aCBjcmVhdGlvbiBvZiBhIFF1bGF0cmljcyBwcm9qZWN0LiBFYWNoIHByb2plY3QgY29uc2lzdHMgb2YgYSBzdXJ2ZXksIGRpc3RyaWJ1dGlvbiByZWNvcmQsIGFuZCBjb2xsZWN0aW9uIG9mIHJlc3BvbnNlcyBhbmQgcmVwb3J0cy4gVGhlcmUgYXJlIHRocmVlIHdheXMgdG8gY3JlYXRlIGEgcXVlc3Rpb25uYWlyZS4gRmlyc3QsIHlvdSBjYW4gY3JlYXRlIGEgbmV3IHN1cnZleSBwcm9qZWN0IGZyb20gc2NyYXRjaC4gU2Vjb25kLCB5b3UgY2FuIGNyZWF0ZSBhIG5ldyBxdWVzdGlvbm5haXJlIGZyb20gYSBjb3B5IG9mIGFuIGV4aXN0aW5nIHF1ZXN0aW9ubmFpcmUuIEV2ZW50dWFsbHksIHlvdSBjYW4gY3JlYXRlIGZyb20gYSB0ZW1wbGF0ZSBpbiB5b3VyIFN1cnZleSBMaWJyYXJ5LCBvciBmcm9tIGFuIGV4cG9ydGVkIFFTRiBmaWxlLg0KDQo6Ojogey5pbmZvYm94IC5kb3dubG9hZCBkYXRhLWxhdGV4PSJ7ZG93bmxvYWR9In0NCltIZXJlIHlvdSBjYW4gZmluZCBhIHRlbXBsYXRlIG9mIGEgcXVlc3Rpb25uYWlyZSBpbiBRdWFsdHJpY3Mgd2l0aCBndWlkZWxpbmVzIGFuZCBzdWdnZXN0aW9ucyByZWxhdGVkIHRvIGVhY2ggcXVlc3Rpb24gdHlwZS5dKC4vRXhhbXBsZVF1ZXN0aW9ubmFpcmVRdWFsdHJpY3MucXNmKQ0KOjo6DQoNCg0KSW4gb3JkZXIgdG8gY3JlYXRlIGEgY29tcGxldGVseSBuZXcgcXVlc3Rpb25uYWlyZSwgeW91IG5lZWQgdG8gZG8gdGhlIGZvbGxvd2luZzogIA0KDQpHbyB0byB0aGUgUHJvamVjdHMgcGFnZSBieSBjbGlja2luZyB0aGUgUXVhbHRyaWMgWE0gbG9nbyBvciBjbGlja2luZyBQcm9qZWN0cyBvbiB0aGUgdG9wLXJpZ2h0LiAgDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnY3JlYXRlLW5ldy1wcm9qZWN0LnBuZycpDQpgYGANCg0KQ3JlYXRlIG5ldyBwcm9qZWN0IGJ5IGNsaWNraW5nIHRoZSBibHVlIGJ1dHRvbiBvbiB0aGUgcmlnaHQgc2lkZS4gIA0KSW4gdGhlICJDcmVhdGUgeW91ciBvd24iIHNlY3Rpb24gY2xpY2sgb24gdGhlIHN1cnZleSBidXR0b24uDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnY3JlYXRlLW5ldy1wcm9qZWN0LTIucG5nJykNCmBgYA0KDQpFbnRlciBhIG5hbWUgZm9yIHlvdXIgc3VydmV5IGFuZCBnZXQgc3RhcnRlZCB3aXRoIGEgc3VydmV5IGNyZWF0aW9uLg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ25ldy1zdXJ2ZXkucG5nJykNCmBgYA0KDQpJZiB5b3Ugd291bGQgbGlrZSB0byBjcmVhdGUgYSBuZXcgcXVlc3Rpb25uYWlyZSBvbiBhIGJhc2lzIG9mIGFuIGFscmVhZHkgZXhpc3Rpbmcgb25lLCB0aGVuIHlvdSBjaG9vc2UgIkZyb20gYSBDb3B5Ii4gU3Vic2VxdWVudGx5LCB5b3UgbmVlZCB0byBpbmRpY2F0ZSB0aGUgcXVlc3Rpb25uYWlyZSB5b3Ugd291bGQgbGlrZSB0byBjb3B5LiBOb3cgeW91IGFyZSBnb29kIHRvIGdvISANCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdzdXJ2ZXktY29weS5wbmcnKQ0KYGBgDQoNCklmIHRoZXJlIGlzIGEgcXVlc3Rpb25uYWlyZSBpbiB0aGUgUXVhbHRyaWNzIExpYnJhcnkgeW91IHdvdWxkIGxpa2UgdG8gdXNlLCB0aGVuIHlvdSBuZWVkIHRvIGNob29zZSAiRnJvbSBMaWJyYXJ5IiwgYW5kIGluZGljYXRlIG9uZSBsaWJyYXJ5IG5hbWUgaW4gdGhlIGRyb3Bkb3duIG1lbnUuIA0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ2xpYnJhcnktc3VydmV5LnBuZycpDQpgYGANCg0KOjo6IHsuaW5mb2JveF9vcmFuZ2UgLmhpbnQgZGF0YS1sYXRleD0ie2hpbnR9In0NCg0KU29tZSB1c2VmdWwgdGlwcyB3aGVuIGNyZWF0aW5nIGEgcXVlc3Rpb25uYWlyZSBpbiBRdWFsdHJpY3M6DQoNCiogQWRkIGEgcHJvZ3Jlc3MgYmFyIHNvIHRoYXQgcmVzcG9uZGVudHMga25vdyBob3cgbWFueSBwYWdlcyBhcmUgbGVmdCAoc2VlICJMb29rICYgRmVlbCIgbWVudSBpbiBRdWFsdHJpY3MpLg0KDQoqIFJlbWVtYmVyIHRvIGFjdGl2YXRlIHRoZSAiRm9yY2UgUmVzcG9uc2UiIGZpZWxkIHVuZGVyICJWYWxpZGF0aW9uIE9wdGlvbnMiIGlmIHlvdSBkb24ndCB3YW50IHRvIGFsbG93IHJlc3BvbmRlbnRzIHRvIHNraXAgcXVlc3Rpb25zLg0KDQoqIENoZWNrIHRoZSB1c2FiaWxpdHkgb24gbW9iaWxlIGRldmljZXMgdXNpbmcgdGhlIHByZXZpZXcgb3B0aW9uIChtYWtlIHN1cmUgdGhlICJNb2JpbGUgZnJpZW5kbHkiIG9wdGlvbiBpcyBjaGVja2VkKS4NCjo6Og0KDQojIyBRdWVzdGlvbm5haXJlDQoNCkFmdGVyIHlvdSBzZXQgdXAgZXZlcnl0aGluZywgeW91IHNob3VsZCBkZXZlbG9wIDIwIC0gMjUgcXVlc3Rpb25zLiBIb3dldmVyLCB0aGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgb2JqZWN0aXZlcyB0byBrZWVwIGluIG1pbmQgd2hpbGUgZGV2ZWxvcGluZyBhIHF1ZXN0aW9ubmFpcmU6DQoNCiogSW5mb3JtYXRpb24geW91IGFyZSBwcmltYXJpbHkgaW50ZXJlc3RlZCBpbiAoZGVwZW5kZW50IHZhcmlhYmxlKQ0KKiBJbmZvcm1hdGlvbiB3aGljaCBtaWdodCBleHBsYWluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKGluZGVwZW5kZW50IHZhcmlhYmxlcykNCiogT3RoZXIgZmFjdG9ycyByZWxhdGVkIHRvIGJvdGggZGVwZW5kZW50IGFuZCBpbmRlcGVuZGVudCBmYWN0b3JzDQoqIFdob+KAmXMgYW5zd2VyaW5nIHRoZSBxdWVzdGlvbnM/DQoNCklmIHlvdSBoYXZlIHNvcnRlZCBvdXQgYWxsIGFuc3dlcnMgb24gdGhlIHByZXZpb3VzIHF1ZXN0aW9ucywgeW91IGFyZSByZWFkeSB0byBzdGFydCB3cml0aW5nIHRoZSBjb250ZW50LiBBZ2FpbiwgaGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgdGhpbmdzIHRvIHJlbWVtYmVyOg0KDQoqIFRoZSBwdXJwb3NlIG9mIHRoZSBxdWVzdGlvbm5haXJlDQoqIFdoeSBpdCBpcyBpbXBvcnRhbnQgZm9yIHlvdSBhbmQgd2h5IGl0IGNvdWxkIGJlIHVzZWZ1bCBmb3IgdGhlIHJlc3BvbmRlbnQNCiogSG93IGxvbmcgaXQgc2hvdWxkIHRha2UgdG8gY29tcGxldGUgJiB0aGUgZmluYWwgZGF0ZSBmb3IgYSByZXBseQ0KKiBBc2sgcXVlc3Rpb25zIGluIGEgbG9naWNhbCBvcmRlciAmIHVzZSB0aGUgcmlnaHQgdHlwZSBvZiBxdWVzdGlvbnMNCiogQWltIGZvciBicmV2aXR5ICYgdXNlIHNpbXBsZSBsYW5ndWFnZQ0KDQojIyMgUXVlc3Rpb25uYWlyZSBhbmQgcmVzZWFyY2ggZGVzaWduIHstfQ0KDQpUaGUgcXVlc3Rpb25uYWlyZSBkZXNpZ24gc2hvdWxkIGJlIGFsaWduZWQgd2l0aCB0aGUgcmVzZWFyY2ggZGVzaWduISBUaGVyZWZvcmUsIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMgd2Ugd2lsbCBleHBsYWluIHNvbWUgc3VnZ2VzdGVkIHN0ZXBzIG9uIGhvdyB0byBhcHByb2FjaCBxdWVzdGlvbm5haXJlIGNyZWF0aW9uLg0KDQpMZXQncyBzdGFydCB3aXRoIHdoYXQgaXMgYSBxdWVzdGlvbm5haXJlLiBBIHN0cnVjdHVyZWQgcXVlc3Rpb25uYWlyZSBpcyBhIHJlc2VhcmNoIGluc3RydW1lbnQgZGVzaWduZWQgdG8gZWxpY2l0IHNwZWNpZmljIGluZm9ybWF0aW9uIGZyb20gYSBzYW1wbGUgb2YgYSB0YXJnZXQgcG9wdWxhdGlvbi4gVXN1YWxseSBpdCBpcyB1c2VkIGluIGEgc3RhbmRhcmRpemVkIHdheSB3aXRoIGZpeGVkLWFsdGVybmF0aXZlIHF1ZXN0aW9ucyAoc2FtZSBxdWVzdGlvbnMgYW5kIHJlc3BvbnNlIG9wdGlvbnMgZm9yIGFsbCByZXNwb25kZW50cykuDQoNCkFuIG9iamVjdGl2ZSBvZiBhIHF1ZXN0aW9ubmFpcmUgaXMgdGhyZWVmb2xkOg0KDQoqIHRvIHRyYW5zbGF0ZSB0aGUgaW5mb3JtYXRpb24gbmVlZCBpbnRvIGEgc2V0IG9mIHNwZWNpZmljIHF1ZXN0aW9ucyB0aGF0IHRoZSByZXNwb25kZW50IGNhbiBhbmQgd2lsbCBhbnN3ZXIsDQoqIHRvIG1vdGl2YXRlLCBhbmQgZW5jb3VyYWdlIHJlc3BvbmRlbnRzIHRvIGJlY29tZSBpbnZvbHZlZCwgdG8gY29vcGVyYXRlLCBhbmQgdG8gY29tcGxldGUgdGhlIHF1ZXN0aW9ubmFpcmUsDQoqIHRvIG1pbmltaXplIHJlc3BvbnNlIGVycm9yLg0KDQojIyMgQ29udGVudCBpbiBhIHF1ZXN0aW9ubmFpcmUgey19DQoNCkluIHRoaXMgc3RlcCB5b3UgYXJlIHN0YXJ0aW5nIHRvIHdvcmsgb24gdGhlIGNvbnRlbnQgb2YgeW91IHF1ZXN0aW9ucy4NCg0KQXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgcXVlc3Rpb25uYWlyZSB5b3Ugc2hvdWxkIGdpdmUgYSBicmllZiBpbnRyb2R1Y3Rpb24gdG8geW91ciByZXNwb25kZW50cyBpbiB0aGUgY29udGV4dCBvZiB5b3VyIHJlc2VhcmNoIGFuZCB0aGUgY29udGVudCBvZiB0aGUgcXVlc3Rpb25uYWlyZS4gVHJ5IHRvIHVzZSBzaW1wbGUgbGFuZ3VhZ2UgYW5kIGF2b2lkIHRlY2huaWNhbCB0ZXJtcy4gQWRkaXRpb25hbGx5LCBpbiB0aGUgaW50cm9kdWN0aW9uIHlvdSBzaG91bGQgc3RhdGUgaG93IGxvbmcgdGhlIHN1cnZleSB3aWxsIGFwcHJveGltYXRlbHkgdGFrZS4gDQoNCldoZW4geW91IHN0YXJ0IHRoaW5raW5nIGFib3V0IHRoZSBxdWVzdGlvbnMgdG8gYXNrLCB0aGVyZSBhcmUgc2V2ZXJhbCBwb2ludHMgdG8gY29uc2lkZXI6ICANCg0KKiBJcyB0aGUgcXVlc3Rpb24gbmVjZXNzYXJ5Pw0KKiBXaWxsIEkgb2J0YWluIHRoZSBuZWVkZWQgaW5mb3JtYXRpb24/ICANCiogQXJlIHNldmVyYWwgcXVlc3Rpb25zIG5lZWRlZCBpbnN0ZWFkIG9mIG9uZT8gIA0KKiBXaGF0IHR5cGUgb2YgZGF0YSBjYW4gSSBjb2xsZWN0IGJ5IGFza2luZyB0aGF0IHF1ZXN0aW9uIChjYXRlZ29yaWNhbCBvciBjb250aW51aW91cyk/ICANCg0KSW4geW91ciBzdXJ2ZXkgdHJ5IHRvIGF2b2lkIGFza2luZyAqKmRvdWJsZS1iYXJyZWxsZWQgcXVlc3Rpb25zLioqVGhvc2UgYXJlIA0KYSBzaW5nbGUgcXVlc3Rpb24gdGhhdCBhdHRlbXB0cyB0byBjb3ZlciB0d28gaXNzdWVzLiBTdWNoIHF1ZXN0aW9ucyBjYW4gYmUgY29uZnVzaW5nIHRvIHJlc3BvbmRlbnRzIGFuZCByZXN1bHQgaW4gYW1iaWd1b3VzIHJlc3BvbnNlcy4gSW5zdGVhZCwgeW91IG1pZ2h0IGFzayBtdWx0aXBsZSBxdWVzdGlvbnMgaW4gb3JkZXIgdG8gb2J0YWluIHRoZSBpbnRlZGVkIGluZm9ybWF0aW9uLiAgDQoNCg0KYGBge2Jsb2NrLCB0eXBlPSJpbmNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpJbmNvcnJlY3QNClx2c3BhY2V7LTAuMWlufQ0KYGBgDQoNCkRvIHlvdSB0aGluayBOaWtlIFRvd24gb2ZmZXJzIGJldHRlciB2YXJpZXR5IGFuZCBwcmljZXMgdGhhbiBvdGhlciBOaWtlIHN0b3Jlcz8gICAgDQoNCmBgYHtibG9jaywgdHlwZT0iaW5jb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMTBpbn0NClx2c3BhY2V7LTAuMTBpbn0NCmBgYA0KDQoNCmBgYHtibG9jaywgdHlwZT0iY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjFpbn0NCkNvcnJlY3QNClx2c3BhY2V7LTAuMWlufQ0KYGBgICAgIA0KDQpEbyB5b3UgdGhpbmsgTmlrZSBUb3duIG9mZmVycyBiZXR0ZXIgdmFyaWV0eSB0aGFuIG90aGVyIE5pa2Ugc3RvcmVzPyAgDQpEbyB5b3UgdGhpbmsgTmlrZSBUb3duIG9mZmVycyBiZXR0ZXIgcHJpY2VzIHRoYW4gb3RoZXIgTmlrZSBzdG9yZXM/DQoNCmBgYHtibG9jaywgdHlwZT0iY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjEwaW59DQpcdnNwYWNley0wLjEwaW59DQpgYGANCiAgICAgICAgICAgDQojIyMgSW5hYmlsaXR5IGFuZCB1bndpbGxpbmduZXNzIHRvIGFuc3dlciB7LX0gIA0KDQpUaGUgcXVhbGl0eSBvZiBjb2xsZWN0ZWQgZGF0YSB5b3UgaGlnaGx5IGRlcGVuZHMgb24geW91ciBhYmlsaXR5IHRvIGFkZHJlc3MgY29ycmVjdCBwYXJ0aWNpcGFudHMuIFRoZXJlZm9yZSwgeW91IG5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgeW91ciByZXNwb25kZW50cyBhcmUgYWJsZSB0byBtZWFuaW5nZnVsbHkgYW5zd2VyIHlvdXIgcXVlc3Rpb25zLiAgIA0KDQpFeGFtcGxlczogIA0KDQoqIE5vdCBldmVyeSBob3VzZWhvbGQgbWVtYmVyIG1pZ2h0IGJlIGluZm9ybWVkIGFib3V0IG1vbnRobHkgZXhwZW5zZXMgZm9yIGdyb2NlcmllcyBwdXJjaGFzZXMgaWYgc29tZW9uZSBlbHNlIG1ha2VzIHRoZXNlIHB1cmNoYXNlcy4gICANCiogVXNlIGZpbHRlciBxdWVzdGlvbnMgdGhhdCBtZWFzdXJlIGZhbWlsaWFyaXR5IGFuZCBwcm9kdWN0IHVzZS4gIA0KKiBJbmNsdWRlIGEg4oCcZG9u4oCZdCBrbm934oCdIG9wdGlvbi4gIA0KKiBJZiB5b3UgYXNrIHBhcnRpY2lwYW50cyBmb3IgbW9udGVyYXkgdmFsdWVzIChlLmcuIGhvdyBtdWNoIGFyZSB5b3UgcmVhZHkgdG8gcGF5IGZvciB0aGUgWFkgcHJvZHVjdD8pIGFjcm9zcyBzZXZlcmFsIEVVLCBtYWtlIHN1cmUgeW91IGluZGljYXRlIGNvcnJlY3QgY3VycmVuY3kgKGUuZy4gSFJLIGZvciBDcm9hdGlhIG9yIEhVRiBmb3IgSHVuZ2FyeSkuICANCiogVGhpbmsgYWJvdXQgaG93IG1vYmlsZSBmcmllbmRseSBpcyB0aGUgbGF5b3V0IG9mIHlvdXIgc3VydmV5IChpZiBpdCBpcyBhbiBvbmxpbmUgc3VydmV5KS4NCiogR29vZCBjYXNlIHByYWN0aWNlcyBzdWdnZXN0IHRoYXQgdGhlcmUgc2hvdWxkIG5vdCBiZSBtb3JlIHRoYW4gMiBxdWVzdGlvbnMgcGVyIHBhZ2UgKGZvciBvbmxpbmUgc3VydmV5cyBkaXNwbGF5ZWQgb24gbW9iaWxlIHBob25lcykuDQoNCg0KDQpJZiB5b3UgYXJlIGFza2luZyBwYXJ0aWNpcGFudHMgdG8gcmVjYWxsIGNlcnRhaW4gYnJhbmRzIGZvciBpbnN0YW5jZSwgbWFrZSBzdXJlIHlvdSB1c2UgKip1bmFpZGVkIHJlY2FsbCBxdWVzdGlvbjoqKiAgDQoNCmBgYHtibG9jaywgdHlwZT0iY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjFpbn0NCkNvcnJlY3QNClx2c3BhY2V7LTAuMWlufQ0KYGBgICAgIA0KDQpXaGF0IGJyYW5kcyBvZiBzb2Z0IGRyaW5rcyBkbyB5b3UgcmVtZW1iZXIgYmVpbmcgYWR2ZXJ0aXNlZCBvbiBUViBsYXN0IG5pZ2h0PyAgDQoNCmBgYHtibG9jaywgdHlwZT0iY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjEwaW59DQpcdnNwYWNley0wLjEwaW59DQpgYGANCg0KDQpgYGB7YmxvY2ssIHR5cGU9ImluY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjFpbn0NCkluY29ycmVjdA0KXHZzcGFjZXstMC4xaW59DQpgYGAgIA0KDQpXaGljaCBvZiB0aGVzZSBicmFuZHMgd2VyZSBhZHZlcnRpc2VkIGxhc3QgbmlnaHQgb24gVFY/ICANCmEpIENvY2EtQ29sYSAgDQpiKSBQZXBzaSAgDQpjKSBSZWQgQnVsbCAgICAgICAgDQpkKSBFdmlhbiAgICAgDQplKSBEb27igJl0IGtub3cNCg0KYGBge2Jsb2NrLCB0eXBlPSJpbmNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xMGlufQ0KXHZzcGFjZXstMC4xMGlufQ0KYGBgDQoNCg0KDQpJZiB5b3UgYXJlIGFza2luZyBwYXJ0aWNpcGFudHMgdG8gbGlzdCBzb21ldGhpbmcsIHRoZSBnb29kIGNhc2UgcHJhY3RpY2UgaXMgKip0byBtaW5pbWl6ZSB0aGUgZWZmb3J0IHJlcXVpcmVkIGJ5IHJlc3BvbmRlbnRzOioqICANCg0KYGBge2Jsb2NrLCB0eXBlPSJjb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KQ29ycmVjdA0KXHZzcGFjZXstMC4xaW59DQpgYGAgIA0KDQpQbGVhc2UgY2hlY2sgYWxsIHRoZSBkZXBhcnRtZW50cyBmcm9tIHdoaWNoIHlvdSBwdXJjaGFzZWQgbWVyY2hhbmRpc2Ugb24geW91ciBtb3N0IHJlY2VudCBzaG9wcGluZyB0cmlwIHRvIGEgZGVwYXJ0bWVudCBzdG9yZTogICAgDQphKSBXb21lbuKAmXMgZHJlc3NlcyAgDQpiKSBNZW7igJlzIGFwcGFyZWwgIA0KYykgQ2hpbGRyZW7igJlzIGFwcGFyZWwgIA0KZCkgQ29zbWV0aWNzICANCmUpIEpld2VscnkgICAgDQpmKSBPdGhlciAocGxlYXNlIHNwZWNpZnkpIF9fX19fX19fX19fDQoNCmBgYHtibG9jaywgdHlwZT0iY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjEwaW59DQpcdnNwYWNley0wLjEwaW59DQpgYGANCg0KYGBge2Jsb2NrLCB0eXBlPSJpbmNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpJbmNvcnJlY3QNClx2c3BhY2V7LTAuMWlufQ0KYGBgICANCg0KUGxlYXNlIGxpc3QgYWxsIHRoZSBkZXBhcnRtZW50cyBmcm9tIHdoaWNoIHlvdSBwdXJjaGFzZWQgbWVyY2hhbmRpc2Ugb24geW91ciBtb3N0IHJlY2VudCBzaG9wcGluZyB0cmlwIHRvIGRlcGFydG1lbnQgc3RvcmUgWC4gICAgDQoNCmBgYHtibG9jaywgdHlwZT0iaW5jb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMTBpbn0NClx2c3BhY2V7LTAuMTBpbn0NCmBgYA0KDQoNCkluIGEgY2FzZSB5b3UgYXJlIGFza2luZyBmb3IgaW5mb3JtYXRpb24gdGhhdCBjb3VsZCBiZSBjb25zaWRlcmVkIHNlbnNpdGl2ZSAoZS5nLiBtb25leSwgZmFtaWx5IGxpZmUsIHBvbGl0aWNhbCBiZWxpZWZzLCByZWxpZ2lvbiksIHRoZXkgc2hvdWxkIGNvbWUgYXQgdGhlIGVuZCBvZiB0aGUgcXVlc3Rpb25uYWlyZS4gTW9yZW92ZXIsIGl0IGlzIHJlY29tbWVuZGFibGUgdG8gcHJvdmlkZSByZXNwb25zZSBjYXRlZ29yaWVzIHJhdGhlciB0aGFuIGFza2luZyBmb3Igc3BlY2lmaWMgZmlndXJlczogIA0KDQpgYGB7YmxvY2ssIHR5cGU9ImNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpDb3JyZWN0DQpcdnNwYWNley0wLjFpbn0NCmBgYCAgDQoNCldoaWNoIG9uZSBvZiB0aGUgZm9sbG93aW5nIGNhdGVnb3JpZXMgYmVzdCBkZXNjcmliZXMgeW91ciBob3VzZWhvbGTigJlzIGFubnVhbCBncm9zcyBpbmNvbWU/ICAgIA0KYSkgdW5kZXIgMjUuMDAxIOKCrCAgICANCmIpIDI1LjAwMeKCrCB0byA1MC4wMDAg4oKsICAgIA0KYykgNTAuMDAx4oKsIHRvIDc1LjAwMCDigqwgICAgDQpkKSA3NS4wMDHigqwgdG8gMTAwLjAwMCDigqwgICANCmUpIG92ZXIgMTAwLjAwMCDigqwgICANCg0KYGBge2Jsb2NrLCB0eXBlPSJjb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMTBpbn0NClx2c3BhY2V7LTAuMTBpbn0NCmBgYA0KDQoNCmBgYHtibG9jaywgdHlwZT0iaW5jb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KSW5jb3JyZWN0DQpcdnNwYWNley0wLjFpbn0NCmBgYCAgDQoNCldoYXQgaXMgeW91ciBob3VzZWhvbGTigJlzIGV4YWN0IGFubnVhbCBpbmNvbWU/DQoNCmBgYHtibG9jaywgdHlwZT0iaW5jb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMTBpbn0NClx2c3BhY2V7LTAuMTBpbn0NCmBgYA0KDQojIyMgRGVjaWRlIG9uIG1lYXN1cmVtZW50IHNjYWxlcyBhbmQgc2NhbGluZyB0ZWNobmlxdWVzIHstfQ0KDQpFdmVyeSBzdGF0aXN0aWNhbCBhbmFseXNpcyByZXF1aXJlcyB0aGF0IHZhcmlhYmxlcyBoYXZlIGEgc3BlY2lmaWMgbGV2ZWxzIG9mIG1lYXN1cmVtZW50LiBNZWFzdXJlbWVudCBzY2FsZXMgeW91IGNob29zZSBmb3IgeW91ciBxdWVzdGlvbnMgaW4gYSBzdXJ2ZXkgd2lsbCBhZmZlY3QgdGhlIGFuc3dlcnMgeW91IGdldCBhbmQgZXZlbnR1YWxseSBzdGF0aXN0aWNhbCB0ZXN0IHlvdSBjYW4gYXBwbHkuDQpGb3IgaW5zdGFuY2UsIGl0IHdvdWxkIG5vdCBtYWtlIHNlbnNlIHRvIGNvbXB1dGUgYW4gYXZlcmFnZSBvZiBnZW5kZXJzLiBBbiBhdmVyYWdlIG9mIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgZG9lcyBub3QgbWFrZSBtdWNoIHNlbnNlLiBNb3Jlb3ZlciwgaWYgeW91IHRyaWVkIHRvIGNvbXB1dGUgdGhlIGF2ZXJhZ2Ugb2YgZ2VuZGVycyBkZWZpbmVkIGluIG51bWVyaWMgdmFsdWVzIChlLmcuIG1hbGU9MCwgZmVtYWxlPTEpLCB0aGUgb3V0cHV0IHdvdWxkIGJlIGludGVycHJldGFibGUuDQoNCjo6OiB7LmluZm9ib3hfcmVkIC5jYXV0aW9uIGRhdGEtbGF0ZXg9IntjYXV0aW9ufSJ9DQpJdCBpcyBjcnVjaWFsIHRvIGJlY29tZSBmYW1pbGlhciB3aXRoIHBvc3NpYmlsaXRpZXMgb2YgZWFjaCBzY2FsZSAqKmJlZm9yZSoqIHlvdSBjaG9vc2UgdG8gYWRkIGFub3RoZXIgcXVlc3Rpb24gdG8geW91ciBzdXJ2ZXkuIENvbnNlcXVlbnRseSwgY2hhbmNlcyB0byBvYnRhaW4gZGF0YSB5b3UgZGlkIG5vdCBpbnRlbmQgdG8gY29sbGVjdCBhbmQgY2hhbmNlcyB0aGF0IHlvdSB3aWxsIG5vdCBiZSBhYmxlIHRvIGFwcGx5IHRlc3RzIHlvdSBpbnRlbmRlZCBhcmUgc2lnbmlmaWNhbnRseSBsb3dlci4NCjo6Og0KDQpJbiB0aGUgZm9sbG93aW5nIHRhYmxlIHlvdSBjYW4gZ2V0IGEgcXVpY2sgb3ZlcnZpZXcgb2YgcG9zc2liaWxpdGllcyBwZXIgZWFjaCBtZWFzdXJlbWVudCBzY2FsZS4gOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoID0gJzkwJScsZmlnLmFsaWduPSdjZW50ZXInfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm1lYXN1cmVtZW50LXNjYWxlLnBuZyIpDQpgYGANCg0KSW4gdGhlIHRhYmxlIGJlbG93IHlvdSBjYW4gZmluZCBnZW5lcmFsIHByb2NlZHVyZSBmb3IgY2hvb3NpbmcgYSBjb3JyZWN0IGFuYWx5c2lzIGJhc2VkIG9uIHRoZSBtZWFzdXJlbWVudCBzY2FsZSBvZiB5b3VyIGRhdGEgYW5kIG51bWJlciBvZiB2YXJpYWJsZXMuIEl0IHNob3dzIHN0YXRpc3RpY2FsIGFuYWx5c2VzIHdlIGNvdmVyZWQgZHVyaW5nIHRoZSBjb3Vyc2UgYW5kIGFpbXMgdG8gaGVscCB5b3UgY2hvb3NlIGFtb25nIHRoZW0gYmFzZWQgb24gdGhlIG5hdHVyZSBvZiBkZXBlbmRlbnQgdmFyaWFibGVzIG9uIHRoZSBzaWRlLCBhbmQgdGhlIG5hdHVyZSBhbmQgdGhlIG51bWJlciBvZiB5b3VyIGluZGVwZW5kZW50IHZhcmlhYmxlcyBvbiB0aGUgb3RoZXIgc2lkZTogDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGggPSAnOTAlJyxmaWcuYWxpZ249J2NlbnRlcid9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygib3ZlcnZpZXctc3RhdGlzdGljYWwtdGVzdC5qcGciKQ0KYGBgDQoNCjo6OiB7LmluZm9ib3hfcmVkIC5jYXV0aW9uIGRhdGEtbGF0ZXg9IntjYXV0aW9ufSJ9DQpJdCBpcyBoaWdobHkgcmVjb21tZW5kZWQgdG8gdGhpbmsgYWJvdXQgd2hhdCB0eXBlIG9mIGRhdGEgeW91IHdhbnQgdG8gY29sbGVjdCBhbmQgd2hhdCB0ZXN0IHRvIHVzZSwgYmVmb3JlIHlvdSBmb3JtIGEgcXVlc3Rpb24gYW5kIGFkZCB0byB0aGUgc3VydmV5LiBXZSBoaWdobHkgcmVjb21tZW5kIHlvdSBOT1QgdG8gYWRkIHF1ZXN0aW9ucyB3aXRob3V0IHRoaW5raW5nIHdoYXQgdHlwZSBvZiBkYXRhIHlvdSBhcmUgZ29pbmcgdG8gY29sbGVjdCB3aXRoIGl0LiBJZiB5b3UgZG8gc28sIHlvdSBtYXkgZW5kIHVwIHdpdGggZGF0YSB5b3UgZGlkIG5vdCB3YW50IHRvIGNvbGxlY3QsIGFuZCBtb3Jlb3Zlciwgd2l0aCBkYXRhIHVuc3VpdGFibGUgZm9yIHRoZSB0ZXN0IHlvdSBpbnRlbmRlZCB0byB1c2UuDQoNCkhlcmUgeW91IGNhbiBmaW5kIGV4dHJlbWVseSBuaWNlIG92ZXJ2aWV3IG9mIHN0YXRpc3RpY2FsIHRlc3QgYXNzb2NpYXRlZCB3aXRoIGRpZmZlcmVudCB0eXBlcyBvZiB2YXJpYWJsZXM6IFtDSE9PU0lORyBUSEUgQ09SUkVDVCBTVEFUSVNUSUNBTCBURVNUIC0gVUNMQV0oaHR0cHM6Ly9zdGF0cy5pZHJlLnVjbGEuZWR1L290aGVyL211bHQtcGtnL3doYXRzdGF0LykNCg0KOjo6DQoNCg0KIyMjIFRoZSBtb3N0IGZyZXF1ZW50IHR5cGVzIG9mIHF1ZXN0aW9ucyB7LX0NCg0KSGVyZSB3ZSB3YW50IHRvIHNob3cgeW91IHRoZSBtb3N0IGZyZXF1ZW50IHR5cGVzIG9mIHF1ZXN0aW9ucyBzdHVkZW50cyB1c2UgYW5kIHdoYXQgdHlwZSBvZiBkYXRhIGNhbiBiZSBjb2xsZWN0ZWQgYnkgdXNpbmcgdGhlbS4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgcmVzdWx0cz0nYXNpcycsIHdhcm5pbmc9RkFMU0UgLGVycm9yPUZBTFNFfQ0KDQojIExvYWQgaW4gcXVhbHRSaWNzIHBhY2thZ2UNCmxpYnJhcnkocXVhbHRSaWNzKQ0KbGlicmFyeShqYW5pdG9yKQ0KbGlicmFyeShzamxhYmVsbGVkKQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KDQojIFJlYWQgdGhlIHF1YWx0cmljcyBzdXJ2ZXkgZGF0YQ0KcXVhbHRyaWNzPC1yZWFkX3N1cnZleSgnbmV3X3F1YWx0cmljc19yZXNwb25zZV9kYXRhX2ZpbmFsX2ZpbmFsLmNzdicpDQoNCiMgVXNpbmcgbGFiZWxzIGFzIGNvbHVtbiBuYW1lDQoNCm5ldy5jb2xuYW1lcyA8LWNvbG5hbWVzKGxhYmVsX3RvX2NvbG5hbWVzKHF1YWx0cmljcykpDQpuZXcuY29sbmFtZXMgPC0gbWFrZS51bmlxdWUobmV3LmNvbG5hbWVzLCBzZXA9Il8iKQ0KY29sbmFtZXMocXVhbHRyaWNzKTwtIG5ldy5jb2xuYW1lcw0KDQpgYGANCg0KIyMjIyBNdWx0aXBsZSBjaG9pY2UgcXVlc3Rpb24gey19DQoNCk11bHRpcGxlIENob2ljZSB3aXRoIGEgc2luZ2xlIGFuc3dlciBpcyBhIHR5cGUgb2YgY2xvc2VkLWVuZGVkIHF1ZXN0aW9uIHRoYXQgbGV0cyByZXNwb25kZW50cyBzZWxlY3QgKipvbmUgYW5zd2VyKiogZnJvbSBhIGRlZmluZWQgbGlzdCBvZiBjaG9pY2VzLlR5cGUgb2YgZGF0YSB5b3Ugb2J0YWluIGlzICoqY2F0ZWdvcmljYWwuKiogDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJScsIGZpZy5jYXA9Ik11bHRpcGxlIGNob2ljZSBxdWVzdGlvbiB3aXRoIHNpbmdsZSBhbnN3ZXIifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3N1cHBvcnQtbXVsdGlwbGUtY2hvaWNlLXF1ZXN0aW9uLnBuZycpDQpgYGANCg0KOjo6IHsuaW5mb2JveF9vcmFuZ2UgLmhpbnQgZGF0YS1sYXRleD0ie2hpbnR9In0NCg0KU3RhdGlzdGljYWwgdGVzdCB0aGF0IHlvdSBjYW4gdGhpbmsgb2Ygd2hlbiBhbmFseXNpbmcgY2F0ZWdvcmljYWwgZGF0YToNCg0KKiAqKkZpc2hlcidzIGV4YWN0IHRlc3QqKg0KICAgICsgVXNlZCB3aGVuIGZyZXF1ZW5jeSBpbiBhdCBsZWFzdCBvbmUgY2VsbCBpcyAqKmxlc3MgdGhhbiA1ICoqLiBXaGVuIGZyZXF1ZW5jaWVzIGluIGVhY2ggY2VsbCBhcmUgZ3JlYXRlciB0aGFuIDUsIENoaS1zcXVhcmUgdGVzdCBzaG91bGQgYmUgdXNlZA0KICAgICsgMSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kICAxIGluZGVwZW5kZW50IHZhcmlhYmxlIHdpdGggMiBvciBtb3JlIGxldmVscy9mYWN0b3JzDQogICAgKyBIeXBvdGhlc2lzOiBJcyB0aGVyZSBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gZnJlcXVlbmNpZXMgYmV0d2VlbiB2YWx1ZXMgb2JzZXJ2ZWQgaW4gY2VsbHMgYW5kIHZhbHVlcyBleHBlY3RlZCBpbiBjZWxscw0KDQoqIENoaS1zcXVhcmUgdGVzdA0KICAgICsgKipHb29kbmVzcyBvZiBmaXQ6ICoqIHdoZW4geW91IG9ubHkgaGF2ZSAxIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgbm9uZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMNCiAgICAgICAgLSBIeXBvdGhlc2lzOiBJcyB0aGVyZSBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gZnJlcXVlbmNpZXMgYmV0d2VlbiB2YWx1ZXMgb2JzZXJ2ZWQgaW4gY2VsbHMgYW5kIHZhbHVlcyBleHBlY3RlZCBpbiBjZWxscyA/DQogICAgKyAqKkNoaS1TcXVhcmUgVGVzdCBvZiBJbmRlcGVuZGVuY2U6Kiogd2hlbiB5b3UgaGF2ZSAxIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgIDEgaW5kZXBlbmRlbnQgdmFyaWFibGUgd2l0aCAyIG9yIG1vcmUgbGV2ZWxzL2ZhY3RvcnMuDQogICAgICAgIC0gSHlwb3RoZXNpczogSXMgdGhlcmUgYW4gYXNzb2NpYXRpb24gYmV0d2VlbiBjYXRlZ29yaWNhbCB2YXJpYWJsZSBYIGFuZCBjYXRlZ29yaWNhbCB2YXJpYWJsZSBZPw0KICAgICAgICANCiogKipCaW5vbWlhbCBsb2dpc3RpYyByZWdyZXNzaW9uKioNCiAgICArIFVzZWQgd2hlbiB5b3UgaGF2ZSBhbiBpbmRlcGVuZGVudCB2YXJpYWJsZSBvZiBhdCBsZWFzdCBpbnRlcnZhbCBzY2FsZSBhbmQgZGVwZW5kZW50IHZhcmlhYmxlIGlzIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgdGhhdCBjYW4gdGFrZSBvbiBleGFjdGx5IHR3byB2YWx1ZXMgKDEgb3IgMCwgaS5lLiwgeWVzIG9yIG5vKS4NCg0KKiBDYXRlZ29yaWNhbCB2YXJpYWJsZXMgY2FuIGJlIHVzZWQgYXMgcHJlZGljdG9ycyBpbiByZWdyZXNzaW9uIChhcyBkdW1teSB2YXJpYWJsZXMpLg0KDQo6OjoNCg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MiUnLGZpZy5jYXA9Ik11bHRpcGxlIGNob2ljZSBxdWVzdGlvbiB3aXRoIG11bHRpcGxlIGFuc3dlcnMifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ211bHRpcGxlLWNob2ljZS1xdWVzdGlvbi1tdWx0aXBsZS1hbnN3ZXJzLnBuZycpDQpgYGANCg0KSXQgaXMgaW1wb3J0YW50IHRvIGRpc3Rpbmd1aXNoIG11bHRpcGxlIGNob2ljZSBxdWVzdGlvbnMgd2l0aCBzaW5nbGUgYW5kIG11bHRpcGxlIGFuc3dlcnMgKHdoaWNoIHdpbGwgYmUgcHJlc2VudGVkIGxhdGVyKSBhcyB0aGVpciBhbmFseXNpcyBsb29rcyBkaWZmZXJlbnRseS4NCg0KRm9yIHRoZSBhbmFseXNpcyBvZiByZXN1bHRzIGNvbGxlY3RlZCB3aXRoIG11bHRpcGxlIGNob2ljZSBxdWVzdGlvbiB3aXRoIG11bHRpcGxlIHBvc3NpYmxlIGFuc3dlcnMsIHdlIGNhbiB1c2UgKipDb2NocmFuJ3MgUSB0ZXN0LioqIEFsdGhvdWdoIHdlIGRpZCBub3QgbWVudGlvbiBpdCBiZWZvcmUsIGl0IGlzIG5vdCB0b28gZGlmZmVyZW50IGZyb20gd2hhdCB5b3UgaGF2ZSBhbHJlYWR5IGxlYXJuZWQgYWJvdXQgb3RoZXIgdGVzdHMuIA0KDQo6Ojogey5pbmZvYm94X29yYW5nZSAuaGludCBkYXRhLWxhdGV4PSJ7aGludH0ifQ0KVGhlIENvY2hyYW7igJlzIFEgdGVzdCBhbmQgYXNzb2NpYXRlZCBtdWx0aXBsZSBjb21wYXJpc29ucyByZXF1aXJlIHRoZSBmb2xsb3dpbmcgYXNzdW1wdGlvbnM6DQoNCiAgMS4gUmVzcG9uc2VzIGFyZSBkaWNob3RvbW91cyBhbmQgZnJvbSBrIG51bWJlciBvZiBtYXRjaGVkIHNhbXBsZXMuDQogIDIuIFRoZSBzdWJqZWN0cyBhcmUgaW5kZXBlbmRlbnQgb2Ygb25lIGFub3RoZXIgYW5kIHdlcmUgc2VsZWN0ZWQgYXQgcmFuZG9tIGZyb20gYSBsYXJnZXIgcG9wdWxhdGlvbi4NCiAgMy4gVGhlIHNhbXBsZSBzaXplIGlzIHN1ZmZpY2llbnRseSDigJxsYXJnZeKAnS4gKEFzIGEgcnVsZSBvZiB0aHVtYiwgdGhlIG51bWJlciBvZiBzdWJqZWN0cyBmb3Igd2hpY2ggdGhlIHJlc3BvbnNlcyBhcmUgbm90IGFsbCAw4oCZcyBvciAx4oCZcywgbiwgc2hvdWxkIGJlIOKJpSA0IGFuZCBuayBzaG91bGQgYmUg4omlIDI0KQ0KOjo6DQoNCiMjIyMgUmFuayBvcmRlciBxdWVzdGlvbiB7LX0NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJywgZmlnLmNhcD0iUmFuayBvcmRlciBxdWVzdGlvbiJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygncmFuay1vcmRlci1xdWVzdGlvbi5wbmcnKQ0KYGBgDQoNCkEgcmFuayBvcmRlciBxdWVzdGlvbiBhc2tzIHJlc3BvbmRlbnRzIHRvIGNvbXBhcmUgaXRlbXMgdG8gZWFjaCBvdGhlciBieSBwbGFjaW5nIHRoZW0gaW4gb3JkZXIgb2YgcHJlZmVyZW5jZS4gTm90ZSB0aGF0IHRoZSBkYXRhIG9idGFpbmVkIGZyb20gYSByYW5rIG9yZGVyIHF1ZXN0aW9uIHNob3dzIGFuIG9yZGVyIG9mIGEgcmVzcG9uZGVudCdzIHByZWZlcmVuY2UsIGJ1dCBub3QgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBpdGVtcy4gRm9yIGluc3RhbmNlLCBpZiBpdCB0dXJucyBvdXQgdGhhdCB0aGUgbW9zdCBpbXBvcnRhbnQgZmVhdHVyZSBvZiBhIGZpdG5lc3MgdHJhY2tlciBmb3IgYSByZXNwb25kZW50IFhZIGlzICJNZWFzdXJpbmcgc3RlcHMiIGFuZCB0aGUgc2Vjb25kIG1vc3QgaW1wb3J0YW50IGZlYXR1cmUgIkNhbG9yaWVzIGJ1cm5lZCIsIHdlIGRvbid0IGtub3cgZm9yIGhvdyBtdWNoIG1vcmUgaW1wb3J0YW50IGlzIHRoZSBmb3JtZXIgb25lIGluIGNvbXBhcmlzb24gdG8gdGhlIGxhdHRlciBvbmUuIA0KDQpJbiBvcmRlciB0byBhbmFseXplIHJlc3VsdHMgZnJvbSBhIHJhbmsgb3JkZXIgcXVlc3Rpb24sIHdlIHVzZSAqKkZyaWVkbWFuIHJhbmsgc3VtIHRlc3QuKioNCg0KOjo6IHsuaW5mb2JveF9vcmFuZ2UgLmhpbnQgZGF0YS1sYXRleD0ie2hpbnR9In0NCkZyaWVkbWFuIHJhbmsgc3VtIHRlc3QgaXMgdXNlZCB0byBpZGVudGlmeSB3aGV0aGVyIHRoZXJlIGFyZSBhbnkgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBkaXN0cmlidXRpb25zIG9mIDMgb3IgbW9yZSBwYWlyZWQgZ3JvdXBzLiBJdCBpcyB1c2VkIHdoZW4gdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9ucyBmb3IgdXNpbmcgb25lLXdheSByZXBlYXRlZCBtZWFzdXJlcyBBTk9WQSBhcmUgbm90IG1ldC4gQW5vdGhlciBjYXNlIHdoZW4gRnJpZWRtYW4gcmFuayBydW0gdGVzdCBpcyB1c2VkIGlzIHdoZW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBpcyBtZWFzdXJlZCBvbiBhbiBvcmRpbmFsIHNjYWxlLCBhcyBpbiBvdXIgY2FzZS4NCjo6Og0KDQojIyMjIENvbnN0YW50IFN1bSBxdWVzdGlvbiB7LX0NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJywgZmlnLmNhcD0iQ29uc3RhbnQgc3VtIHF1ZXN0aW9uIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdjb25zdGFudC1zdW0tcXVlc3Rpb24ucG5nJykNCmBgYA0KDQpJZiB5b3Ugd2lzaCB0byBvYnRhaW4gaW5mb3JtYXRpb24gYWJvdXQgaG93IG11Y2ggb25lIGF0dHJpYnV0ZSBpcyBwcmVmZXJyZWQgb3ZlciBhbm90aGVyIG9uZSwgeW91IG1heSB1c2UgYSBjb25zdGFudCBzdW0gc2NhbGUuIFRoZSB0b3RhbCBib3ggc2hvdWxkIGFsd2F5cyBiZSBkaXNwbGF5ZWQgYXQgdGhlIGJvdHRvbSB0byBtYWtlIGl0IGVhc2llciBmb3IgcmVzcG9uZGVudHMuIEEgY29uc3RhbnQgc3VtIHF1ZXN0aW9uIHBlcm1pdHMgY29sbGVjdGlvbiBvZiByYXRpbyBkYXRhIHR5cGUuIFdpdGggZGF0YSBvYnRhaW5lZCB3ZSB3b3VsZCBiZSBhYmxlIHRvIGV4cHJlc3MgdGhlIHJlbGF0aXZlIGltcG9ydGFuY2Ugb2YgdGhlIG9wdGlvbnMuDQoNCldpdGggdGhlIGRhdGEgY29sbGVjdGVkIHdlIGFyZSBhYmxlIHRvIGFuc3dlciB0aGUgcXVlc3Rpb246IHdoYXQgZmFjdG9yIGlzIHRoZSBtb3N0IGltcG9ydGFudCBmb3Igb3VyIHJlc3BvbmRlbnRzIHdoZW4gdGhleSBnbyBvdXQgZm9yIGEgZGlubmVyPw0KDQpJbiBvcmRlciB0byBhbnN3ZXIgdGhpcyBxdWVzdGlvbiB3ZSBuZWVkIHRvIGNvbmR1Y3QgKiphIHJlcGVhdGVkIG1lYXN1cmVzIEFOT1ZBKiouDQoNCjo6OiB7LmluZm9ib3hfb3JhbmdlIC5oaW50IGRhdGEtbGF0ZXg9IntoaW50fSJ9DQpUaGlzIHR5cGUgb2YgQU5PVkEgaXMgdXNlZCBmb3IgYW5hbHl6aW5nIGRhdGEgd2hlcmUgdGhlIHNhbWUgc3ViamVjdHMgYXJlIG1lYXN1cmVkIG1vcmUgdGhhbiBvbmNlLiBJbiBvdXIgY2FzZSB3ZSBoYXZlIGV2ZXJ5IHJlc3BvbmRlbnQgbWVhc3VyZWQgb24gZWFjaCBvZiB0aGUgZmFjdG9ycyAobG9jYXRpb25zLCBwcmljZSwgYW1iaWVuY2UgYW5kIGN1c3RvbWVyIHNlcnZpY2UpLiBSZXBlYXRlZCBtZWFzdXJlcyBBTk9WQSBpcyBhbiBleHRlbnNpb24gb2YgdGhlIHBhaXJlZC1zYW1wbGVzIHQtdGVzdC4gVGhpcyB0ZXN0IGlzIGFsc28gcmVmZXJyZWQgdG8gYXMgYSB3aXRoaW4tc3ViamVjdHMgQU5PVkEuIEluIHRoZSB3aXRoaW4tc3ViamVjdCBleHBlcmltZW50YWwgZGVzaWduIHRoZSBzYW1lIGluZGl2aWR1YWxzIGFyZSBtZWFzdXJlZCBvbiB0aGUgc2FtZSBvdXRjb21lIHZhcmlhYmxlIHVuZGVyIGRpZmZlcmVudCB0aW1lIHBvaW50cyBvciBjb25kaXRpb25zLg0KOjo6DQoNCiMjIyMgVGV4dCBvciBudW1iZXIgZW50cnkgcXVlc3Rpb24gey19DQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJScsIGZpZy5jYXA9IlRleHQgb3IgbnVtYmVyIGVudHJ5IHF1ZXN0aW9uIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdpbWFnZXMvdGV4dC1lbnRyeS5QTkcnKQ0KYGBgDQoNCkEgdGV4dCBvciBudW1iZXIgZW50cnkgcXVlc3Rpb24gaXMgYSByZWNvbW1lbmRlZCB0eXBlIG9mIHF1ZXN0aW9uIGlmIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiBvYnRhaW5pbmcgcmF0aW8gZGF0YSB0eXBlLiBXZSB3aWxsIHVzZSB0aGlzIHR5cGUgb2YgcXVlc3Rpb24gdG9nZXRoZXIgd2l0aCBhIGNvbnN0YW50IHN1bSBxdWVzdGlvbiB0eXBlIHRvIGNvbGxlY3QgZGF0YSB0aGF0IGNhbiBiZSBhbmFseXNlZCB3aXRoIHJlZ3Jlc3Npb24gYW5hbHlzaXMuIE5vdGUgdGhhdCBpbiB0aGlzIGNhc2Ugd2UgdHJlYXQgY29uc3RhbnQgc3VtIGRhdGEgYXMgcmF0aW8gZGF0YSBhbmQgdGhlcmVmb3JlIGFzc3VtZSB0aGF0IDAgbWVhbnMgY29tcGxldGUgYWJzZW5jZS4gIA0KDQojIyMgU2NhbGluZyB0ZWNobmlxdWVzIHstfQ0KDQpXaGVuIGl0IGNvbWVzIHRvIHNjYWxpbmcgdGVjaG5pcXVlcywgdGhleSBhcmUgbWVhbnQgdG8gc3R1ZHkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG9iamVjdHMuIFRoZSBiYXNpYyBzY2FsaW5nIHRlY2huaXF1ZXMgY2xhc3NpZmljYXRpb24gaXMgb24gKipjb21wYXJhdGl2ZSoqIGFuZCAqKm5vbi1jb21wYXJhdGl2ZSBzY2FsZXMqKi4gDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGggPSAnOTAlJyxmaWcuYWxpZ249J2NlbnRlcid9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygic2NhbGVzLnBuZyIpDQpgYGANCg0KKipUaGUgbm9uY29tcGFyYXRpdmUgc2NhbGUqKiBlYWNoIG9iamVjdCBpcyBzY2FsZWQgaW5kZXBlbmRlbnRseSBvZiB0aGUgb3RoZXIgb2JqZWN0cy4gVGhlIHJlc3VsdGluZyBkYXRhIGlzIHN1cHBvc2VkIHRvIGJlIG1lYXN1cmVkIGluIGFuIGludGVydmFsIGFuZCByYXRpbyBzY2FsZWQuDQoNCioqQ29tcGFyYXRpdmUgc2NhbGVzIChvciBub25tZXRyaWMgc2NhbGluZykqKiBjb21wYXJlIGRpcmVjbHR5IHRoZSBzdGltdWx1cyBvYmplY3QuIEZvciBleGFtcGxlLCB0aGUgcmVzcG9uZGVudCBtaWdodCBiZSBhc2tlZCBkaXJlY3RseSBhYm91dCBoaXMgcHJlZmVyZW5jZSBiZXR3ZWVuIGRvbWVzdGljIGFuZCBmb3JlaWduIGJlZXIgYnJhbmRzLiBBcyBhIHJlc3VsdCwgdGhlIGNvbXBhcmF0aXZlIGRhdGEgY29sbGVjdGVkIGNhbiBvbmx5IGJlIGludGVycHJldGVkIGluIHJlbGF0aXZlIHRlcm1zLiBJbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zIHdlIHdpbGwgd2FsayB0aHJvdWdoIGJvdGggdHlwZXMgb2YgY29tcGFyYXRpdmUgc2NhbGVzIGFuZCBicmllZmx5IGludHJvZHVjZSB0aGVtLg0KDQoNCiMjIyMgQ29tcGFyYXRpdmUgc2NhbGU6IFBhaXJlZCBDb21wYXJpc29uIHstfSAgICANCg0KKiBSZXNwb25kZW50IGlzIHByZXNlbnRlZCB3aXRoIHR3byBvYmplY3RzIGFuZCBhc2tlZCB0byBzZWxlY3Qgb25lIGFjY29yZGluZyB0byBzb21lIGNyaXRlcmlvbi4NCiogVGhlIG5hdHVyZSBvZiByZXN1bHRpbmcgZGF0YSBpcyBvcmRpbmFsDQoqIEFzc3VtcHRpb24gb2YgdHJhbnNpdGl2aXR5IChpZiBYID4gWSBhbmQgWSA+IFosIHRoZW4gWCA+IFopIGVuYWJsZXMgdGhlIHBhaXJlZCBjb21wYXJpc29uIGRhdGEgdG8gYmUgY29udmVydGVkIGludG8gYSByYW5rIG9yZGVyLiBUbyBkbyBzbywgeW91IG5lZWQgdG8gaW5kZXRpZnkgdGhlIG51bWJlciBvZiB0aW1lcyB0aGUgb2JqZWN0IGlzIHByZWZlcnJlZCBieSBhZGRpbmcgdXAgYWxsIHRoZSBtYXRyaWNlcy4NCiogRWZmZWN0aXZlIHdoZW4gdGhlIG51bWJlciBvZiBvYmplY3RzIGlzIGxpbWl0ZWQgYXMgaXQgcmVxdWlyZXMgdGhlIGRpcmVjdCBjb21wYXJpc29uLCBhbmQgYSBiaWdnZXIgbnVtYmVyIG9mIG9iamVjdHMgbWFrZXMgdGhlIGNvbXBhcmlzb24gYmVjb21lcyB1bm1hbmFnYWJsZS4NCiogKkV4YW1wbGU6KiAgDQpGb3IgZWFjaCBwYWlyLCBwbGVhc2UgaW5kaWNhdGUgd2hpY2ggb2YgdGhlIHR3byBicmFuZHMgb2YgYmVlciBpbiB0aGUgcGFpciB5b3UgcHJlZmVyLg0KYGBge3IsIGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSc5MCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3BhaXJlZCBjb21wYXJpc29uLnBuZycpDQpgYGANCg0KIyMjIyBDb21wYXJhdGl2ZSBzY2FsZTogUmFuayBPcmRlciB7LX0gIA0KDQoqIEFsbG93IGEgY2VydGFpbiBzZXQgb2YgYnJhbmRzIG9yIHByb2R1Y3RzIHRvIGJlIHNpbXVsdGFuZW91c2x5IHJhbmtlZCBiYXNlZCB1cG9uIGEgc3BlY2lmaWMgYXR0cmlidXRlIG9yIGNoYXJhY3RlcmlzdGljLg0KKiBUaGUgcmFuayBvcmRlciBzY2FsaW5nIGlzIGEgZ29vZCBwcm94eSBmb3IgdG8gdGhlIHNob3BwaW5nIHNldHRpbmcgYXMgdGhlcmUgYXJlIHNpbXVsdGFuZW91cyBjb21wYXJpc29ucyBvZiBvYmplY3RzLg0KKiBUaGUgcmFuayBvcmRlciBzY2FsaW5nIHJlc3VsdHMgaW4gdGhlIGRhdGEgb2Ygb3JkaW5hbCBuYXR1cmUuDQoqICpFeGFtcGxlOiogIA0KUmFuayB0aGUgdmFyaW91cyBicmFuZHMgb2YgYmVlciBpbiBvcmRlciBvZiBwcmVmZXJlbmNlLiBCZWdpbiBieSBwaWNraW5nIG91dCB0aGUgb25lIGJyYW5kIHRoYXQgeW91IGxpa2UgbW9zdCBhbmQgYXNzaWduIGl0IGEgbnVtYmVyIDEuIFRoZW4gZmluZCB0aGUgc2Vjb25kIG1vc3QgcHJlZmVycmVkIGJyYW5kIGFuZCBhc3NpZ24gaXQgYSBudW1iZXIgMi4gQ29udGludWUgdGhpcyBwcm9jZWR1cmUgdW50aWwgeW91IGhhdmUgcmFua2VkIGFsbCB0aGUgYnJhbmRzIG9mIGJlZXIgaW4gb3JkZXIgb2YgcHJlZmVyZW5jZS4NCk5vIHR3byBicmFuZHMgc2hvdWxkIHJlY2VpdmVkIHRoZSBzYW1lIHJhbmsgbnVtYmVyLg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc1MCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3Jhbmstb3JkZXItc2NhbGUucG5nJykNCmBgYA0KDQojIyMjIENvbXBhcmF0aXZlIHNjYWxlOiBDb25zdGFudCBzdW0gey19ICANCg0KKiBSZXNwb25kZW50cyBhbGxvY2F0ZSBhIGNvbnN0YW50IHN1bSBvZiB1bml0cyAoZS5nLiwgcG9pbnRzLCBkb2xsYXJzKSBhbW9uZyBhIHNldCBvZiBzdGltdWx1cyBvYmplY3RzIHdpdGggcmVzcGVjdCB0byBzb21lIGNyaXRlcmlvbi4gIA0KKiBDb25zdGFudCBzdW0gaXMgc2ltaWxhciB0byByYW5rIG9yZGVyLCBidXQgaXQgY2FycmllcyBzcGVjaWZpYyB1bml0cy4gIA0KKiBUaGUgcmVzdWx0aW5nIGRhdGEgZG9lcyBub3QganVzdCBpbmRpY2F0ZSBpbXBvcnRhbnQgZmFjdG9ycywgYnV0IGFsc28gYnkgaG93IG11Y2ggYSBmYWN0b3Igc3VwZXJzZWRlcyBhbm90aGVyIG9uZS4gIA0KKiBDb25zdGFudCBzdW0gc2NhbGluZyBjYW4gYmUgdXNlZCB0byBvYnNlcnZlIHRoZSBjb21wYXJhdGl2ZSBzaWduaWZpY2FuY2UgcmVzcG9uZGVudHMgYXNzaWduZWQgdG8gdmFyaW91cyBmYWN0b3JzIG9mIGEgc3ViamVjdC4gIA0KKiAqRXhhbXBsZToqICANClRoZXJlIGFyZSA4IGF0dHJpYnV0ZXMgb2YgYm90dGxlZCBiZWVycy4gUGxlYXNlIGFsbG9jYXRlIDEwMCBwb2ludHMgYW1vbmcgdGhlIGF0dHJpYnV0ZXMgc28gdGhhdCB5b3VyIGFsbG9jYXRpb24gcmVmbGVjdHMgdGhlIHJlbGF0aXZlIGltcG9ydGFuY2UgeW91IGF0dGFjaCB0byBlYWNoIGF0dHJpYnV0ZS4NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nODAlJ30NCmtuaXRyOjogaW5jbHVkZV9ncmFwaGljcygnY29uc3RhbnQtc3VtLXNjYWxlLnBuZycpDQpgYGANCg0KKiBCYXNpYyBhbmFseXNpcyBvZiBjb25zdGFudC1zdW0gZGF0YSBpbnZvbHZlcyB0YWJ1bGF0aW9uIG9mIHJlc3BvbnNlcyBhbmQgcHJlc2VudGluZyB0aGVtIGFzIGVpdGhlciBxdWFudGl0aWVzIChlLmcuLCAib24gYXZlcmFnZSwgNyBwb2ludHMgd2VyZSBhbGxvY2F0ZWQgdG8gImhpZ2ggYWxjb2hvbCBsZXZlbCIpLCBvciwgYXMgcHJvcG9ydGlvbnMgKCJPbiBhdmVyYWdlLCA3JSBvZiBwb2ludHMgd2VyZSBhbGxvY2F0ZWQgdG8gImhpZ2ggYWxjb2hvbCBsZXZlbCIpLiAgDQoNCg0KIyMjIyBOb24tQ29tcGFyYXRpdmUgU2NhbGVzOiBDb250aW51b3VzIFJhdGluZyBTY2FsZXMgey19ICANCg0KKiBQYXJ0aWNpcGFudHMgcmF0ZSB0aGUgb2JqZWN0cyBieSBwbGFjaW5nIGEgbWFyayBhdCB0aGUgYXBwcm9wcmlhdGUgcG9zaXRpb24gb24gYSBsaW5lIHRoYXQgcnVucyBmcm9tIG9uZSBleHRyZW1lIG9mIHRoZSBjcml0ZXJpb24gdmFyaWFibGUgdG8gdGhlIG90aGVyLiAgDQoqIE9uZSBvZiB0aGUgYWR2YW50YWdlcyBvZiB0aGUgY29udGludW91cyByYXRpbmcgc2NhbGUgaXMgdGhhdCBpdCBpcyBlYXN5IHRvIGFkbWluaXN0ZXIuICANCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdjb250aW51b3VzLXJhdGluZy1zY2FsZS5wbmcnKQ0KYGBgDQoNCiogT25jZSB0aGUgcmF0aW5ncyBhcmUgY29sbGVjdGVkLCB5b3UgY2FuIHNwbGl0cyB1cCB0aGUgb2J0YWluZWQgcmF0aW5ncyBpbnRvIGNhdGVnb3JpZXMgYW5kIHRoZW4gYXNzaWduIHRob3NlIGRlcGVuZGluZyBvbiB0aGUgY2F0ZWdvcnkgaW4gd2hpY2ggdGhlIHJhdGluZ3MgZmFsbC4NCg0KDQojIyMjIE5vbi1Db21wYXJhdGl2ZSBTY2FsZXM6IEl0ZW1pemVkIFJhdGluZyBTY2FsZXMgey19IA0KDQoqIFRoZSByZXNwb25kZW50cyBhcmUgcHJvdmlkZWQgd2l0aCBhIHNjYWxlIHRoYXQgaGFzIGEgbnVtYmVyIG9yIGJyaWVmIGRlc2NyaXB0aW9uIGFzc29jaWF0ZWQgd2l0aCBlYWNoIGNhdGVnb3J5LiAgDQoqIFRoZSBjYXRlZ29yaWVzIGFyZSBvcmRlcmVkIGluIHRlcm1zIG9mIHNjYWxlIHBvc2l0aW9uLCBhbmQgdGhlIHJlc3BvbmRlbnRzIGFyZSByZXF1aXJlZCB0byBzZWxlY3QgdGhlIHNwZWNpZmllZCBjYXRlZ29yeSB0aGF0IGJlc3QgZGVzY3JpYmVzIHRoZSBvYmplY3QgYmVpbmcgcmF0ZWQuICANCiogVGhlIGNvbW1vbmx5IHVzZWQgaXRlbWl6ZWQgcmF0aW5nIHNjYWxlcyBhcmUgKip0aGUgTGlrZXJ0LCBzZW1hbnRpYyBkaWZmZXJlbnRpYWwgYW5kIFN0YXBlbCBzY2FsZXMuKioNCg0KIyMjIyMgSXRlbWl6ZWQgUmF0aW5nIFNjYWxlczogTGlrZXJ0IHNjYWxlIHstfQ0KDQoqIFJlcXVpcmVzIHJlc3BvbmRlbnRzIHRvIGluZGljYXRlIHRoZWlyIGF0dGl0dWRlIHRvd2FyZHMgdGhlIGdpdmVuIG9iamVjdCB0aHJvdWdoIHRoZSBkZWdyZWUgb2YgYWdyZWVtZW50IG9yIGRpc2FncmVlbWVudCB3aXRoIGVhY2ggb2YgYSBzZXJpZXMgb2Ygc3RhdGVtZW50cyB3aXRoaW4gdHlwaWNhbGx5IGZpdmUgb3Igc2V2ZW4gY2F0ZWdvcmllcy4gIA0KKiBSZXZlcnNlZCBjb2RlIG9mIHNvbWUgaXRlbXMgaW5jcmVhc2VzIHZhbGlkaXR5LiAgDQoqIE9uZSBsaW1pdGF0aW9uIGlzIHRpbWUgcmVxdWlyZWQgdG8gYW5zd2VyIGEgcXVlc3Rpb24gb24gYSBMaWtlcnQgc2NhbGUuIENvbXBhcmVkIHRvIG90aGVyIGl0ZW1pemVkIHNjYWxpbmcgdGVjaG5pcXVlcywgTGlrZXJ0IHNjYWxlIGlzIG1vcmUgdGltZSBjb25zdW1pbmcgYXMgZWFjaCByZXNwb25kZW50IGlzIHJlcXVpcmVkIHRvIHJlYWQgZXZlcnkgc3RhdGVtZW50IGdpdmVuIGluIGEgcXVlc3Rpb25uYWlyZSBiZWZvcmUgYXNzaWduaW5nIGEgbnVtZXJpY2FsIHZhbHVlIHRvIGl0Lg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ2xpa2VydC5wbmcnKQ0KYGBgDQoNCkluIHRoZSB0YWJsZSBiZWxvdyB5b3UgY2FuIGZpbmQgYSBjb3VwbGUgb2YgY29tbW9ubHkgbWVhc3VyZWQgY29uc3RydWN0cyBpbiBtYXJrZXRpbmcgcmVzZWFyY2ggc3VjaCBhcyBhdHRpdHVkZSwgaW1wb3J0YW5jZSwgcHVyY2hhc2UgaW50ZW50aW9uIGFuZCBzaW1pbGFyLg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ2xpa2VydC1tYXJrZXRpbmctcmVzZXJhY2gucG5nJykNCmBgYA0KDQoNCiMjIyMjIEl0ZW1pemVkIFJhdGluZyBTY2FsZXM6IFNlbWFudGljIERpZmZlcmVudGlhbCB7LX0NCg0KKiBUeXBpY2FsbHksIHBhcnRpY2lwYW50cyByYXRlIG9iamVjdHMgb24gYSBudW1iZXIgb2YgaXRlbWl6ZWQsIHNldmVuLXBvaW50IHJhdGluZyBzY2FsZXMgYm91bmRlZCBhdCBlYWNoIGVuZCBieSBvbmUgb2YgdHdvIGJpcG9sYXIgYWRqZWN0aXZlcy4gIA0KDQoqIFNlbWFudGljIGRpZmZlcmVudGlhbCBjYW4gbWVhc3VyZSByZXNwb25kZW50IGF0dGl0dWRlcyB0b3dhcmRzIHNvbWV0aGluZyAocHJvZHVjdHMsY29uY2VwdHMsIGl0ZW1zLCBwZW9wbGUuLi4pLg0KDQoqIEl0IGhlbHBzIHlvdSBmaW5kIHRoZSByZXNwb25kZW50J3MgcG9zaXRpb24gaXMgb24gYSBzY2FsZSBiZXR3ZWVuIHR3byBiaXBvbGFyIGFkamVjdGl2ZXMgc3VjaCBhcyDigJxTd2VldC1Tb3Vy4oCdIG9yIOKAnEJyaWdodC1EYXJr4oCdLiBJbiBjb21wYXJpc29uIHRvIExpa2VydCBzY2FsZSwgd2hpY2ggdXNlcyBnZW5lcmljIHNjYWxlcyAoZS5nLiBleHRyZW1lbHkgZGlzc2F0aXNmaWVkIHRvIGV4dHJlbWVseSBzYXRpc2ZpZWQpLCBzZW1hbnRpYyBkaWZmZXJlbnRpYWwgcXVlc3Rpb25zIGFyZSBwb3NlZCB3aXRoaW4gdGhlIGNvbnRleHQgb2YgZXZhbHVhdGluZyBhdHRpdHVkZXMuDQoNCiogV2lkZWx5IHVzZWQgcmF0aW5nIHNjYWxlIGluIG1hcmtldGluZyByZXNlYXJjaCBkdWUgdG8gaXRzIHZlcnNhdGlsaXR5DQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnc2VtYW50aWMtZGlmZmVyZW50aWFsLnBuZycpDQpgYGANCg0KV2hlbiBjcmVhdGluZyBhIHNlbWFudGljYWwgZGlmZmVyZW5jZSBxdWVzdGlvbiwgeW91IHNob3VsZCBjb25zaWRlciB0aGUgZm9sbG93aW5nOg0KDQoqICoqTnVtYmVyIG9mIGNhdGVnb3JpZXM6KiogDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nbGVmdCcsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3NlbWFudGljLWRpZmZlcmVudGlhbC0xLnBuZycpDQpgYGANCg0KKiAqKkJhbGFuY2VkIHZzLiB1bmJhbGFuY2VkOioqDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nbGVmdCcsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3NlbWFudGljLWRpZmZlcmVudGlhbC0yLnBuZycpDQpgYGANCg0KKiAqKk9kZC9ldmVuIG51bWJlciBvZiBjYXRlZ29yaWVzOioqDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nbGVmdCcsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3NlbWFudGljLWRpZmZlcmVudGlhbC0zLnBuZycpDQpgYGANCg0KKiAqKkZvcmNlZCB2cy4gbm9uLWZvcmNlZCByZXNwb25zZSoqDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nbGVmdCcsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3NlbWFudGljLWRpZmZlcmVudGlhbC00LnBuZycpDQpgYGANCg0KKiAqKlZlcmJhbCBkZXNjcmlwdGlvbjoqKg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2xlZnQnLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdzZW1hbnRpYy1kaWZmZXJlbnRpYWwtNS5wbmcnKQ0KYGBgDQoNCg0KDQojIyMgUXVlc3Rpb25uYWlyZSBzdHJ1Y3R1cmUgey19DQoNClRoZSBzZXF1ZW5jZSBvZiBxdWVzdGlvbnMgaW4gYSBxdWVzdGlvbm5haXJlIGNvdWxkIHBsYXkgaW1wb3J0YW50IHJvbGUuIEZvciBpbnN0YW5jZSwgbW9yZSBzZW5zaXRpdmUgcXVlc3Rpb25zIChzdWNoIGFzIGRlbW9ncmFwaGljLXJlbGF0ZWQgcXVlc3Rpb25zKSBhcmUgdXN1YWxseSBwbGFjZWQgYXQgdGhlIGVuZCBhcyB0aGV5IGNhbiB0cmlnZ2VyIGNoYW5nZSBpbiByZXNwb25kZW50J3MgYmVoYXZpb3IuIA0KDQpJZiB5b3UgcGxhbiB0byBjb25kdWN0IGFuIG9ubGluZSBzdXJ2ZXksIHRoZW4geW91IG5lZWQgdG8gdGhpbmsgYWJvdXQgdGhlIHJlc3BvbmRlbnQncyBleHBlcmllbmNlIHdoaWxlIGRvaW5nIHlvdXIgcXVlc3Rpb25uYWlyZS4gRm9yIGluc3RhbmNlLCBzcHJlYWQgdGhlIGNvbnRlbnQgb3ZlciBtb3JlIHNob3J0IHBhZ2VzIGFuZCBkbyBub3QgaGF2ZSBmZXdlciBsb25nIHBhZ2VzLiBJbiBvbmxpbmUgc3VydmV5cywgdHdvIHF1ZXN0aW9ucyBvbiBvbmUgcGFnZSBpcyBhIHVzZWZ1bCBydWxlIG9mIHRodW1iLiBHZW5lcmFsbHksIHJlc3BvbmRlbnRzIGFyZSByZWx1Y3RhbnQgdG8gcmVhZCBhbmQgZmlsbCBvdXQgbG9uZyBxdWVzdGlvbm5haXJlIHBhZ2VzLiBIZW5jZSwgbG9uZyBwYWdlcyB3aWxsIGxlYWQgdG8gYSBoaWdoZXIgZHJvcG91dCByYXRlLg0KSW4gb3JkZXIgdG8gcmVkdWNlIGRyb3BvdXQgcmF0ZSBzdGF0ZSBob3cgbG9uZyB0aGUgc3VydmV5IHdpbGwgYXBwcm94aW1hdGVseSB0YWtlIGluIHRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlIHF1ZXN0aW9ubmFpcmUuIFRha2UgaW50byBhY2NvdW50IHRoYXQgdG9vbHMgbGlrZSBRdWFsdHJpY3MgcHJvdmlkZSB0aGUgZXN0aW1hdGVkIHJlc3BvbnNlIHRpbWUgaW4gdGhlIHN1cnZleSBvdmVydmlldy4NCg0KOjo6IHsuaW5mb2JveF9yZWQgLmNhdXRpb24gZGF0YS1sYXRleD0ie2NhdXRpb259In0NCkNvbnNpZGVyIHRoYXQgdGhlIG1vc3Qgb2YgcGVvcGxlIHVzdWFsbHkgdXNlIHRoZWlyIHBob25lcyB0byBmaWxsIGl0IG91dC4gVGhpbmsgYWJvdXQgaG93IHRoZSBxdWVzdGlvbm5haXJlIHdpbGwgYXBwZWFyIG9uIGEgcGhvbmUgc2NyZWVuIHRvby4gSW4gdGhhdCByZWdhcmQsIHRoaW5rIG9mIGxlbmd0aCBvZiBxdWVzdGlvbnMgZXNwZWNpYWxseS4NCjo6Og0KDQpJbiB0aGUgZW5kLCB0aGUgcXVlc3Rpb25uYWlyZSBzdHJ1Y3R1cmUgaGFzIHRvIGJlIGFsaWduZWQgd2l0aCB0aGUgcmVzZWFyY2ggZGVzaWduLiBGb3IgZXhhbXBsZSwgaWYgeW91ciByZXNlYXJjaCBkZXNpZ24gZmVhdHVyZXMgYW4gZXhwZXJpbWVudCwgdGhpcyBuZWVkcyB0byBiZSByZWZsZWN0ZWQgaW4gdGhlIHF1ZXN0aW9ubmFpcmUgKGUuZy4sIHlvdSBuZWVkIHRvIGFzc2lnbiB0aGUgcmVzcG9uZGVudHMgcmFuZG9tbHkgdG8gdGhlIGV4cGVyaW1lbnRhbCBjb25kaXRpb25zIGluIGNhc2Ugb2YgYSBiZXR3ZWVuLXN1YmplY3RzIGNvbXBhcmlzb24pLg0KDQojIyMjIFF1ZXN0aW9ubmFpcmUgc3RydWN0dXJlIGZvciBhIGJldHdlZW4tc3ViamVjdHMgZGVzaWduIHstfQ0KDQpJbiBhIGJldHdlZW4tc3ViamVjdCBkZXNpZ24geW91IHJhbmRvbWx5IGFzc2lnbiBlYWNoIHJlc3BvbmRlbnQgdG8gZGlmZmVyZW50IGV4cGVyaW1lbnRhbCBjb25kaXRpb25zLiBUaGV5IHdvdWxkIHRoZW4gY29tcGxldGUgdGFza3Mgb25seSBpbiB0aGUgY29uZGl0aW9uIHRvIHdoaWNoIHRoZXkgYXJlIGFzc2lnbmVkLg0KDQpGb3IgaW5zdGFuY2UsIHdlIHdvdWxkIGxpa2UgdG8gdGVzdCB0aGUgZWZmZWN0IG9mIHR3byBhZHZlcnRpc2VtZW50cyBvbiBwdXJjaGFzZSBpbnRlbnRpb24uIFRoZXJlZm9yZSwgb25lIGdyb3VwIG9mIChyYW5kb21seSBhc3NpZ25lZCkgcmVzcG9uZGVudHMgd2lsbCBiZSBleHBvc2VkIHRvIG9uZSBhZHZlcnRpc2VtZW50IHZlcnNpb24gd2hpbGUgdGhlIG90aGVyIGdyb3VwIChvZiByYW5kb21seSBhc3NpZ25lZCByZXNwb25kZW50cykgd2lsbCBiZSBleHBvc2VkIHRvIGFub3RoZXIgdmVyc2lvbi4gQWZ0ZXIgdGhhdCwgYm90aCBncm91cHMgb2YgcmVzcG9uZGVudHMgc2hvdWxkIGV4cHJlc3MgdGhlaXIgd2lsbGluZ25lc3MgdG8gYnV5IHRoZSBhZHZlcnRpc2VkIHByb2R1Y3QuIEV2ZW51dGFsbHksIGlmIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKGUuZy4gd2lsbGluZ25lc3MgdG8gYnV5KSBpcyBtZWFzdXJlZCBvbiBpbnRlcnZhbCBvciByYXRpbyBzY2FsZSwgdGhlbiB5b3UgY2FuIHVzZSBpbmRlcGVuZGVudCB0LXRlc3QgdG8gY29tcGFyZSBncm91cCBtZWFucy4gVGhlIHdob2xlIGV4cGVyaW1lbnRhbCBkZXNpZ24gc2hvdWxkIGJlIG9yZ2FuaXNlZCBhcyBmb2xsb3dpbmc6DQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnYmV0d2Vlbi1zdWJqZWN0LWRlc2lnbi5wbmcnKQ0KYGBgDQoNCg0KIyMjIyBRdWVzdGlvbm5haXJlIHN0cnVjdHVyZSBmb3IgYSB3aXRoaW4tc3ViamVjdHMgZGVzaWduIHstfQ0KDQpUaGlzIHR5cGUgb2YgZXhwZXJpbWVudGFsIGRlc2lnbiBpbnZvbHZlcyBleHBvc2luZyBlYWNoIHJlc3BvbmRlbnQgdG8gYWxsIG9mIHRoZSB1c2VyIGV4cGVyaW1lbnRhbCBjb25kaXRpb25zIHlvdeKAmXJlIHRlc3RpbmcuIFRoaXMgd2F5LCBlYWNoIHJlc3BvbmRlbnQgd2lsbCB0ZXN0IGFsbCBvZiB0aGUgY29uZGl0aW9ucy4NCg0KRm9yIGluc3RhbmNlLCB3ZSB3b3VsZCBsaWtlIHRvIHRlc3QgYWdhaW4gdGhlIGVmZmVjdCBvZiB0d28gYWR2ZXJ0aXNlbWVudHMgb24gcHVyY2hhc2UgaW50ZW50aW9ucywgYnV0IHRoaXMgdGltZSBpbiBhIHdpdGhpbi1zdWJqZWN0IGRlc2lnbi4gRmlyc3QsIGVhY2ggcmVzcG9uZGVudCB3aWxsIGJlIGV4cG9zZWQgdG8gdGhlIGZpcnN0IHZlcnNpb24gb2YgYWR2ZXJ0aXNlbWVudCBhbmQgcmlnaHQgYWZ0ZXIgdGhhdCBhc2tlZCB0byByYXRlIGhpcy9oZXIgd2lsbGluZ25lc3MgdG8gYnV5IHRoZSBhZHZlcnRpc2VkIHByb2R1Y3QuIFN1YnNlcXVlbnRseSwgZWFjaCBwYXJ0aWNpcGFudCB3aWxsIGJlIHNob3duIGFub3RoZXIgdmVyc2lvbiBvZiBhZHZlcnRpc2VtZW50IGFuZCBhZ2FpbiByYXRlIGhpcy9oZXIgd2lsbGluZ25lc3MgdG8gcHVyY2hhc2UgdGhlIGFkdmVydGlzZWQgcHJvZHVjdC4gRmluYWxseSwgd2UgY2FuIGNvbXBhcmUgZ3JvdXAgbWVhbnMgd2l0aCBwYWlyZWQgc2FtcGxlIHQtdGVzdCAoZ2l2ZW4gdGhhdCBkYXRhIGlzIG1lYXN1cmVkIG9uIGludGVydmFsIG9yIHJhdGlvIHNjYWxlKS4gDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnd2l0aGluLXN1YmplY3QtZGVzaWduLnBuZycpDQpgYGANCg0KDQojIyMgUXVlc3Rpb24gd29yZGluZyB7LX0NCg0KR2VuZXJhbGx5LCBxdWVzdGlvbiB3b3JkaW5nIHNob3VsZCBlbmFibGUgZWFjaCByZXNwb25kZW50IHRvIHVuZGVyc3RhbmQgIHF1ZXN0aW9ucyBhbmQgdG8gYmUgYWJsZSB0byBhbnN3ZXIgdGhlbSB3aXRoIHJlbGlhYmlsaXR5LiBSZWxpYWJpbGl0eSBtZWFucyB0aGF0LCBpZiBhIHJlc3BvbmRlbnQgd2FzIGFza2VkIHRoZSBzYW1lIHF1ZXN0aW9uIGFnYWluLCBoZS9zaGUgd291bGQgZ2l2ZSB0aGUgc2FtZSBhbnN3ZXIgYWdhaW4uIEEgbnVtYmVyIG9mIGNvbW1vbiBwcm9ibGVtcyByZWdhcmRpbmcgdGhlIHF1ZXN0aW9uIHdvcmRpbmcgaGF2ZSBiZWVuIGlkZW50aWZpZWQsIHNvIHdlIHdpbGwgYWRkcmVzcyB0aGUgbW9zdCBpbXBvcnRhbnQgb25lcy4gDQoNCkluIG9yZGVyIHRvIGVuc3VyZSByZWxpYWJpbGl0eSwgdGhlIGlzc3VlIGluIHRlcm1zIG9mICoqd2hvLCB3aGF0LCB3aGVuIGFuZCB3aGVyZSoqIHNob3VsZCBiZSBkZWZpbmVkIGluIGVhY2ggcXVlc3Rpb24uICANCg0KYGBge2Jsb2NrLCB0eXBlPSJpbmNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpJbmNvcnJlY3QNClx2c3BhY2V7LTAuMWlufQ0KYGBgICAgIA0KDQoqRXhhbXBsZToqIFdoaWNoIGJyYW5kIG9mIHNoYW1wb28gZG8geW91IHVzZT8gIA0KKipXaG8gKHRoZSByZXNwb25kZW50KToqKiBJdCBpcyBub3QgY2xlYXIgd2hldGhlciB0aGlzIHF1ZXN0aW9uIHJlbGF0ZXMgdG8gdGhlIGluZGl2aWR1YWwgcmVzcG9uZGVudCBvciB0aGUgcmVzcG9uZGVudOKAmXMgdG90YWwgaG91c2Vob2xkLiAgDQoqKldoYXQgKHRoZSBicmFuZCBvZiBzaGFtcG9vKToqKiBJdCBpcyB1bmNsZWFyIGhvdyB0aGUgcmVzcG9uZGVudCBpcyB0byBhbnN3ZXIgdGhpcyBxdWVzdGlvbiBpZiBtb3JlIHRoYW4gb25lIGJyYW5kIGlzIHVzZWQuICANCioqV2hlbiAodW5jbGVhcik6KiogVGhlIHRpbWUgZnJhbWUgaXMgbm90IHNwZWNpZmllZCBpbiB0aGlzIHF1ZXN0aW9uLiBUaGUgcmVzcG9uZGVudCBjb3VsZCBpbnRlcnByZXQgaXQgYXMgbWVhbmluZyB0aGUgc2hhbXBvbyB1c2VkIHRoaXMgbW9ybmluZywgdGhpcyB3ZWVrLCBvciBvdmVyIHRoZSBwYXN0IHllYXIuICANCioqV2hlcmUgKG5vdCBzcGVjaWZpZWQpOioqIEF0IGhvbWUsIGF0IHRoZSBneW0/IFdoZXJlPw0KYGBge2Jsb2NrLCB0eXBlPSJpbmNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpcdnNwYWNley0wLjFpbn0NCmBgYCAgICANCg0KYGBge2Jsb2NrLCB0eXBlPSJjb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KQ29ycmVjdA0KXHZzcGFjZXstMC4xaW59DQpgYGAgIA0KDQoqQSBtb3JlIGNsZWFybHkgZGVmaW5lZCBxdWVzdGlvbiBpczoqICANCldoaWNoIGJyYW5kIG9yIGJyYW5kcyBvZiBzaGFtcG9vIGhhdmUgeW91IHBlcnNvbmFsbHkgdXNlZCBhdCBob21lIGR1cmluZyB0aGUgbGFzdCBtb250aD8gSW4gdGhlIGNhc2Ugb2YgbW9yZSB0aGFuIG9uZSBicmFuZCwgcGxlYXNlIGxpc3QgYWxsIHRoZSBicmFuZHMgdGhhdCBhcHBseS4NCg0KYGBge2Jsb2NrLCB0eXBlPSJjb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KXHZzcGFjZXstMC4xaW59DQpgYGANCg0KKipVc2Ugb3JkaW5hcnkgd29yZHMuKiogV29yZHMgc2hvdWxkIG1hdGNoIHRoZSB2b2NhYnVsYXJ5IGxldmVsIG9mIHRoZSBwYXJ0aWNpcGFudHMuDQoNCmBgYHtibG9jaywgdHlwZT0iaW5jb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KSW5jb3JyZWN0DQpcdnNwYWNley0wLjFpbn0NCmBgYCAgICANCg0K4oCcRG8geW91IHRoaW5rIHRoZSBkaXN0cmlidXRpb24gb2Ygc29mdCBkcmlua3MgaXMgYWRlcXVhdGU/4oCdICAgDQoNCmBgYHtibG9jaywgdHlwZT0iaW5jb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KXHZzcGFjZXstMC4xaW59DQpgYGAgICAgDQoNCg0KYGBge2Jsb2NrLCB0eXBlPSJjb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KQ29ycmVjdA0KXHZzcGFjZXstMC4xaW59DQpgYGAgICAgDQoNCuKAnERvIHlvdSB0aGluayBzb2Z0IGRyaW5rcyBhcmUgZWFzaWx5IGF2YWlsYWJsZSB3aGVuIHlvdSB3YW50IHRvIGJ1eSB0aGVtP+KAnQ0KDQpgYGB7YmxvY2ssIHR5cGU9ImNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpcdnNwYWNley0wLjFpbn0NCmBgYA0KDQoqKkF2b2lkIGRvdWJsZSBuZWdhdGl2ZSBmb3JtKiouIERvdWJsZSBuZWdhdGl2ZSBxdWVzdGlvbiBmb3JtcyBjYW4gY29uZnVzZSByZXNwb25kZW50cywgZXNwZWNpYWxseSB3aGVuIHRoZXkgbmVlZCB0byBhbnN3ZXIgd2l0aCDigJxBZ3JlZeKAnSBvciDigJxEaXNhZ3JlZeKAnS4NCg0KYGBge2Jsb2NrLCB0eXBlPSJpbmNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpJbmNvcnJlY3QNClx2c3BhY2V7LTAuMWlufQ0KYGBgDQoNCkRvIHlvdSB0aGluayB0aGF0IGl0IGlzIG5vdCB1bmNvbW1vbiB0aGF0IGJveXMgcGxheSBiYXNrZXRiYWxsPyAgDQoNCmBgYHtibG9jaywgdHlwZT0iaW5jb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KXHZzcGFjZXstMC4xaW59DQpgYGANCg0KYGBge2Jsb2NrLCB0eXBlPSJjb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KQ29ycmVjdA0KXHZzcGFjZXstMC4xaW59DQpgYGANCg0KSW4geW91ciBvcGluaW9uLCBpcyBpdCBjb21tb24gdGhhdCBib3lzIHBsYXkgYmFza2V0YmFsbD8NCg0KYGBge2Jsb2NrLCB0eXBlPSJjb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KXHZzcGFjZXstMC4xaW59DQpgYGANCg0KKipBdm9pZCBsZWFkaW5nIHF1ZXN0aW9ucy4qKkxlYWRpbmcgcXVlc3Rpb25zIGNsdWUgdGhlIHBhcnRpY2lwYW50IHRvIHdoYXQgdGhlIGFuc3dlciBzaG91bGQgYmUuIFN1Y2ggcXVlc3Rpb25zIGludHJvZHVjZSBhIGJpYXMgaW4gYSBwYXJ0aWN1bGFyIGRpcmVjdGlvbi4gIA0KDQpgYGB7YmxvY2ssIHR5cGU9ImluY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjFpbn0NCkluY29ycmVjdA0KXHZzcGFjZXstMC4xaW59DQpgYGANCg0K4oCcSXMgQ29sZ2F0ZSB5b3VyIGZhdm9yaXRlIHRvb3RocGFzdGU/4oCdICANCg0KYGBge2Jsb2NrLCB0eXBlPSJpbmNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpcdnNwYWNley0wLjFpbn0NCmBgYA0KDQpgYGB7YmxvY2ssIHR5cGU9ImNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpDb3JyZWN0DQpcdnNwYWNley0wLjFpbn0NCmBgYA0KDQrigJxXaGF0IGlzIHlvdXIgZmF2b3JpdGUgYnJhbmQgb2YgdG9vdGhwYXN0ZT/igJ0NCg0KYGBge2Jsb2NrLCB0eXBlPSJjb3JyZWN0IiwgcHVybD1GQUxTRX0NClx2c3BhY2V7LTAuMWlufQ0KXHZzcGFjZXstMC4xaW59DQpgYGANCg0KKipBdm9pZCBhbWJpZ3VvdXMgd29yZHMuKiogV29yZHMgc3VjaCBhcyB1c3VhbGx5LCBub3JtYWxseSwgZnJlcXVlbnRseSwgb2Z0ZW4sIHJlZ3VsYXJseSwgYW5kIG90aGVyIHNpbWlsYXIgd29yZHMsIGRvIG5vdCBkZWZpbmUgZnJlcXVlbmN5IGNsZWFybHkgZW5vdWdoLg0KDQpgYGB7YmxvY2ssIHR5cGU9ImluY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjFpbn0NCkluY29ycmVjdA0KXHZzcGFjZXstMC4xaW59DQpgYGANCg0K4oCcSW4gYSB0eXBpY2FsbHkgbW9udGgsIGhvdyBvZnRlbiBkbyB5b3UgZ28gdG8gYSBtb3ZpZSB0aGVhdGVyIHRvIHNlZSBhIG1vdmllP+KAnSAgDQphKSBOZXZlciAgDQpiKSBPY2Nhc2lvbmFsbHkgIA0KYykgU29tZXRpbWVzICAgDQpkKSBPZnRlbiAgIA0KZSkgUmVndWxhcmx5ICANCg0KYGBge2Jsb2NrLCB0eXBlPSJpbmNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpcdnNwYWNley0wLjFpbn0NCmBgYA0KDQpgYGB7YmxvY2ssIHR5cGU9ImNvcnJlY3QiLCBwdXJsPUZBTFNFfQ0KXHZzcGFjZXstMC4xaW59DQpDb3JyZWN0DQpcdnNwYWNley0wLjFpbn0NCmBgYA0KDQoiSW4gYSB0eXBpY2FsbHkgbW9udGgsIGhvdyBvZnRlbiBkbyB5b3UgZ28gdG8gYSBtb3ZpZSB0aGVhdGVyIHRvIHNlZSBhIG1vdmllPyIgICAgDQphKSBMZXNzIHRoYW4gb25jZSAgDQpiKSAxIG9yIDIgdGltZXMgIA0KYykgMyBvciA0IHRpbWVzICANCmQpIE1vcmUgdGhhbiA0IHRpbWVzDQoNCmBgYHtibG9jaywgdHlwZT0iY29ycmVjdCIsIHB1cmw9RkFMU0V9DQpcdnNwYWNley0wLjFpbn0NClx2c3BhY2V7LTAuMWlufQ0KYGBgDQoNCiMjIyBDaG9vc2UgYWRlcXVhdGUgb3JkZXIgey19DQoNCk9uZSBvZiB0aGUgbGFzdCBzdGVwcyBpbiBhIHByb2Nlc3Mgb2YgZGVzaWduaW5nIGEgcXVlc3Rpb25uYWlyZSBpcyBjaG9vc2luZyBhZGVxdWF0ZSBvcmRlciBvZiBxdWVzdGlvbnMgYW5kIGluc3RydWN0aW9ucyBmb3IgcmVzcG9uZGVudHMuIA0KDQpBdCB0aGUgYmVnaW5uaW5nLCB5b3Ugc2hvdWxkIHByb3ZpZGUgYSBzaG9ydCBhbmQgZWFzeS10by11bmRlcnN0YW5kIGludHJvZHVjdGlvbiB0byB0aGUgdG9waWMuIFVzZSBzaW1wbGUgbGFuZ3VhZ2UgYW5kIGF2b2lkIHRlY2huaWNhbCB0ZXJtcyAoZS5nLiwgbm90IG1hbnkgcGVvcGxlIHdpbGwga25vdyB0aGUgdGVybXMg4oCcbWFudWZhY3R1cmVyIGJyYW5k4oCdIGFuZCDigJxzdG9yZSBicmFuZOKAnSkuIEFkZGl0aW9uYWxseSwgaW4gdGhlIGludHJvZHVjdGlvbiB5b3Ugc2hvdWxkIHN0YXRlIGhvdyBsb25nIHRoZSBzdXJ2ZXkgd2lsbCBhcHByb3hpbWF0ZWx5IHRha2UuDQoNClRoZSBvcGVuaW5nIHF1ZXN0aW9ucyBzaG91bGQgYmUgaW50ZXJlc3RpbmcsIHNpbXBsZSBhbmQgbm9uLXRocmVhdGVuaW5nLg0KVGhleSBhcmUgY3J1Y2lhbCBiZWNhdXNlIGl0IGlzIHRoZSByZXNwb25kZW50J3MgZmlyc3QgZXhwb3N1cmUgdG8gdGhlIHF1ZXN0aW9ubmFpcmUgYW5kIGlzIGxpa2VseSB0byBzZXQgdGhlIHRvbmUgZm9yIHRoZSByZXN0IG9mIHF1ZXN0aW9ucyBpbiB0aGUgcXVlc3Rpb25uYWlyZS4gSWYgdG9vIGRpZmZpY3VsdCB0byB1bmRlcnN0YW5kLCBvciBzZW5zaXRpdmUgaW4gc29tZSB3YXksIHJlc3BvbmRlbnRzIGFyZSBsaWtlbHkgdG8gc3RvcCBhbnN3ZXJpbmcgeW91ciBxdWVzdGlvbnMuIFF1YWxpZnlpbmcgcXVlc3Rpb25zIChvciBzY3JlZW5pbmcgcXVlc3Rpb25zKSBzaG91bGQgc2VydmUgYXMgdGhlIG9wZW5pbmcgcXVlc3Rpb25zIChpZiBhcHBsaWNhYmxlKS4gVGhlaXIgcHVycG9zZSBpcyB0byBpZGVudGlmeSBhIHBvdGVudGlhbCByZXNwb25kZW50IHRoYXQgaXMgZWxpZ2libGUgdG8gcHJvY2VlZCB3aXRoIHRoZSByZXNlYXJjaCBzdXJ2ZXkuDQoNCkFmdGVyIHRoZSBvcGVuaW5nIHBhcnQsIHlvdSBzaG91bGQgZXN0YWJsaXNoIGFuIG9wdGltYWwgcXVlc3Rpb24gZmxvdy4NCkdlbmVyYWwgcXVlc3Rpb25zIHNob3VsZCBwcmVjZWRlIHRoZSBzcGVjaWZpYyBxdWVzdGlvbnMuIFF1ZXN0aW9ucyBvbiBvbmUgc3ViamVjdCwgb3Igb25lIHBhcnRpY3VsYXIgYXNwZWN0IG9mIGEgc3ViamVjdCwgc2hvdWxkIGJlIGdyb3VwZWQgdG9nZXRoZXIuIEl0IG1heSBmZWVsIGNvbmZ1c2luZyB0byBiZSBhc2tlZCB0byByZXR1cm4gdG8gc29tZSBzdWJqZWN0IHRoZXkgdGhvdWdodCB0aGV5IGFscmVhZHkgZ2F2ZSB0aGVpciBvcGluaW9ucyBhYm91dC4NCg0KQXMgcmVzcG9uZGVudHMgYXJlIG1vdmluZyB0b3dhcmRzIHRoZSBlbmQgb2YgdGhlIHF1ZXN0aW9ubmFpcmUsIHRoZXkgYXJlIGxpa2VseSB0byBiZWNvbWUgaW5jcmVhc2luZ2x5IGluZGlmZmVyZW50IGFuZCBtaWdodCBnaXZlIGNhcmVsZXNzIGFuc3dlcnMuIFRoZXJlZm9yZSwgcXVlc3Rpb25zIG9mIHNwZWNpYWwgaW1wb3J0YW5jZSBzaG91bGQgaWRlYWxseSBiZSBpbmNsdWRlZCBpbiB0aGUgZWFybGllciBwYXJ0IG9mIHRoZSBxdWVzdGlvbm5haXJlLiANCg0KRmluYWxseSwgeW91IHNob3VsZCBwYXkgcGFydGljdWxhciBhdHRlbnRpb24gdG8gcHJvdmlkZSBhbGwgcHJlc2NyaWJlZCBkZWZpbml0aW9ucyBhbmQgZXhwbGFuYXRpb25zIGJlZm9yZSB5b3UgYXNrIGEgcXVlc3Rpb24uIFRoaXMgZW5zdXJlcyB0aGF0IHRoZSBxdWVzdGlvbnMgYXJlIHVuZGVyc3Rvb2QgaW4gY29uc2lzdGVudCB3YXkgYnkgZXZlcnkgcmVzcG9uZGVudC4NCg0KIyMjIFRlc3QgeW91ciBxdWVzdGlvbm5haXJlIHstfQ0KDQpGaW5hbGx5LCBiZWZvcmUgeW91IGRpc3RyaWJ1dGUgdGhlIGZpbmFsIHF1ZXN0aW9ubmFpcmUsIHRoZXJlIGFyZSBzb21lIHRoaW5ncyB0byBjb25zaWRlci4gRmlyc3QsIHlvdSBzaG91bGQgYWx3YXlzIHByZXRlc3QgeW91ciBxdWVzdGlvbm5haXJlIGJlZm9yZSBzaGFyaW5nIGl0IQ0KVGVzdCBhbGwgYXNwZWN0cyBvZiB0aGUgcXVlc3Rpb25uYWlyZSAoY29udGVudCwgd29yZGluZywgc2VxdWVuY2UsIGZvcm0gJiBsYXlvdXQsIGV0Yy4pLiBJZiBwb3NzaWJsZSwgdXNlIHJlc3BvbmRlbnRzIGluIHRoZSBwcmV0ZXN0IHRoYXQgYXJlIHNpbWlsYXIgdG8gdGhvc2Ugd2hvIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIGFjdHVhbCBzdXJ2ZXkuIElkZWFsbHksIHRoZSBwcmV0ZXN0IHNhbXBsZSBzaXplIHNob3VsZCBiZSBzbWFsbCAoaW4gYSByZWFsIHNjZW5hcmlvIHRoaXMgY291bGQgdmFyeSBmcm9tIDE1IHRvIDMwIHJlc3BvbmRlbnRzOyBmb3IgdGhlIGdyb3VwIHByb2plY3QsIGEgbG93ZXIgbnVtYmVyIHdpbGwgYmUgc3VmZmljaWVudCkuIEFmdGVyIGVhY2ggc2lnbmlmaWNhbnQgcmV2aXNpb24gb2YgdGhlIHF1ZXN0aW9ubmFpcmUsIGNvbmR1Y3QgYW5vdGhlciBwcmV0ZXN0LCB1c2luZyBhIGRpZmZlcmVudCBzYW1wbGUgb2YgcmVzcG9uZGVudHMuIEV2ZW50dWFsbHksIGNvZGUgYW5kIGFuYWx5emUgdGhlIHJlc3BvbnNlcyBvYnRhaW5lZCBmcm9tIHRoZSBwcmV0ZXN0IHNvIHRoYXQgeW91IG1ha2Ugc3VyZSB0aGF0IHlvdSBjb2xsZWN0ZWQgaW5mb3JtYXRpb24geW91IGludGVuZGVkIHRvIGNvbGxlY3QuDQoNCkFmdGVyIHRlc3RpbmcgeW91ciBxdWVzdGlvbm5haXJlIHlvdSBzaG91bGQgYmUgYWJsZSB0byBkZXRlcm1pbmUgd2hldGhlcjoNCg0KKiBUaGUgcXVlc3Rpb25zIGFyZSBwcm9wZXJseSBmcmFtZWQgIA0KKiBUaGUgcXVlc3Rpb25zIHdvcmRpbmcgdHJpZ2dlcnMgYW55IGJpYXNlcyAgDQoqIFRoZSBxdWVzdGlvbnMgYXJlIHBsYWNlZCBpbiB0aGUgb3B0aW1hbCBvcmRlciAgDQoqIFRoZSBxdWVzdGlvbnMgYXJlIHVuZGVyc3RhbmRhYmxlICANCiogU3BlY2lmeWluZyBxdWVzdGlvbnMgYXJlIG5lZWRlZCBvciBzb21lIG5lZWQgdG8gYmUgZWxpbWluYXRlZCAgDQoNCiMjIFBpdGNoLCByZXZpc2lvbiAmIHN1Ym1pc3Npb24NCg0KQXQgdGhpcyBzdGFnZSwgeW91IHNob3VsZCBiZSByZWFkeSBmb3IgcGl0Y2hpbmcgeW91ciBxdWVzdGlvbm5haXJlLiBQbGVhc2Uga2VlcCBpbiBtaW5kIHRoZSB0aW1ldGFibGUuDQoNCmBgYHtyIGV2YWwgPSBUUlVFLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpteXRhYmxlX3N1YiA9IGRhdGEuZnJhbWUoDQogICAgRGF0ZV9BID0gYygiT2N0LiAyMSIsIA0KICAgICAgICAgICAgICJPY3QuIDIzKiIsIA0KICAgICAgICAgICAgICJOb3YuIDEiDQogICAgICAgICAgICAgKSwNCiAgICBUaW1lX0EgPSBjKA0KICAgICAgIjExOjU5UE0iLCIwOTowMEFNIC0gMDI6MzBQTSIsIjExOjU5UE0iDQogICAgKSxEYXRlX0IgPSBjKCJPY3QuIDI1IiwgDQogICAgICAgICAgICAgIk9jdC4gMjcqIiwgDQogICAgICAgICAgICAgIk5vdi4gNCINCiAgICAgICAgICAgICApLA0KICAgIFRpbWVfQiA9IGMoDQogICAgICAiMTE6NTlQTSIsIjAyOjAwUE0gLSAwODowMFBNIiwiMTE6NTlQTSINCiAgICApLA0KICAgIFRhc2sgPSBjKCAgIiogU3VibWl0IHF1ZXN0aW9ubmFpcmUgZHJhZnQiLCANCiAgICAgICAgICAgICAgICIqIENvYWNoaW5nOiBRdWVzdGlvbm5haXJlIGRlc2lnbiAobGl2ZSB2aWRlbyBjb2FjaGluZykiLCANCiAgICAgICAgICAgICAgICIqIFN1Ym1pdCByZXZpc2VkIHF1ZXN0aW9ubmFpcmUiDQogICAgICAgICAgICAgICApLA0KICAgIENoYXB0ZXJzID0gYygiMTAiLCIxMCIsIjEwIiksDQogICAgTGluayA9IGMoIiIsDQogICAgICAgICAgICAgICAgICJUQkMiLCANCiAgICAgICAgICAgICAgICAgIiINCiAgICAgICAgICAgICAgICAgKQ0KICAgICkNCg0KI3BhbmRlcjo6cGFuZGVyKG15dGFibGVfc3ViLCBrZWVwLmxpbmUuYnJlYWtzID0gVFJVRSwgc3R5bGUgPSAnZ3JpZCcsIGp1c3RpZnkgPSAnbGVmdCcpDQpteXRhYmxlX3N1YiAlPiUga2FibGUoZXNjYXBlID0gVCkgJT4lDQogIGthYmxlX3BhcGVyKGMoImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICJEYXRlcyBhbmQgdGltZXMgYXJlIGluZGljYXRlZCBmb3IgZ3JvdXBzIEEgYW5kIEIgcmVzcGVjdGl2ZWx5Lg0KICAgICAgICAgICBTZXNzaW9ucyBpbmRpY2F0ZWQgd2l0aCAnKicgYXJlIGdyb3VwIGNvYWNoaW5nIHNlc3Npb25zLiBTbG90cyBvZiA0NSBtaW4uIGFyZSBhc3NpZ25lZCB0byBlYWNoIGdyb3VwIHdpdGhpbiB0aGUgaW5kaWNhdGVkIHRpbWVzLiIsDQogICAgICAgICAgIGdlbmVyYWxfdGl0bGUgPSAiTm90ZTogIiwgDQogICAgICAgICAgIGZvb3Rub3RlX2FzX2NodW5rID0gVCwgdGl0bGVfZm9ybWF0ID0gYygiaXRhbGljIikNCiAgICAgICAgICAgKSANCiMlPiUgICByb3dfc3BlYyhjKDEsMyw2KSwgYmFja2dyb3VuZCA9ICIjRTBFMEUwIikNCmBgYA0KDQoNCiMgUGFydCAyOiBDb2xsZWN0aW5nIGRhdGEgYW5kIGFuYWx5c2lzIHstfQ0KDQojIyBEYXRhIGFuYWx5c2lzIHstfQ0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCByZXN1bHRzPSdhc2lzJywgd2FybmluZz1GQUxTRSAsZXJyb3I9RkFMU0V9DQoNCiMgTG9hZCBpbiBxdWFsdFJpY3MgcGFja2FnZQ0KbGlicmFyeShxdWFsdFJpY3MpDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KHNqbGFiZWxsZWQpDQoNCiMgUmVhZCB0aGUgcXVhbHRyaWNzIHN1cnZleSBkYXRhDQpxdWFsdHJpY3M8LXJlYWRfc3VydmV5KCduZXdfcXVhbHRyaWNzX3Jlc3BvbnNlX2RhdGFfZmluYWxfZmluYWwuY3N2JykNCg0KIyBVc2luZyBsYWJlbHMgYXMgY29sdW1uIG5hbWUNCg0KbmV3LmNvbG5hbWVzIDwtY29sbmFtZXMobGFiZWxfdG9fY29sbmFtZXMocXVhbHRyaWNzKSkNCm5ldy5jb2xuYW1lcyA8LSBtYWtlLnVuaXF1ZShuZXcuY29sbmFtZXMsIHNlcD0iXyIpDQpjb2xuYW1lcyhxdWFsdHJpY3MpPC0gbmV3LmNvbG5hbWVzDQoNCmBgYA0KDQpJbiB0aGlzIGNoYXB0ZXIgd2Ugd2lsbCBlbmNvdW50ZXIgdGhlIG5hdHVyZSBvZiBkYXRhIHlvdSBjb2xsZWN0IHdoZW4gY29uZHVjdGluZyBhIHN1cnZleS4gSXQgd2lsbCBoZWxwIHlvdSBjaG9vc2UgYSB0eXBlIG9mIGEgcXVlc3Rpb24gZGVwZW5kaW5nIG9uIHRoZSBuYXR1cmUgb2YgZGF0YSB5b3Ugd2FudCB0byBjb2xsZWN0IGFuZCBvbiB0aGUgdHlwZSBvZiBzdGF0aXN0aWNhbCB0ZXN0cyB5b3Ugd2FudCB0byBhcHBseS4NCg0KDQojIyMgTXVsdGlwbGUgY2hvaWNlIHdpdGggYSBzaW5nbGUgYW5zd2VyIHstfQ0KDQpNdWx0aXBsZSBDaG9pY2Ugd2l0aCBhIHNpbmdsZSBhbnN3ZXIgaXMgYSB0eXBlIG9mIGNsb3NlZC1lbmRlZCBxdWVzdGlvbiB0aGF0IGxldHMgcmVzcG9uZGVudHMgc2VsZWN0ICoqb25lIGFuc3dlcioqIGZyb20gYSBkZWZpbmVkIGxpc3Qgb2YgY2hvaWNlcy4NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdzdXBwb3J0LW11bHRpcGxlLWNob2ljZS1xdWVzdGlvbi5wbmcnKQ0KYGBgDQoNClR5cGUgb2YgZGF0YSB5b3Ugb2J0YWluIGlzICoqY2F0ZWdvcmljYWwqKiwgYW5kIHRoZSBvdXRwdXQgY29tZXMgaW4gdGhlIGZvbGxvd2luZyBmb3JtOiAgDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsZXZhbD1GQUxTRX0NCnF1YWx0cmljc1sxOjYsYygiSW4gYSB0eXBpY2FsIHdlZWssIGhvdyBtYW55IGhvdXJzIGRvIHlvdSBzcGVuZCB3YXRjaGluZyBtb3ZpZXMgb3IgVFYgc2VyaWVzIG9uIE5ldGZsaXg/IildICU+JQ0KICBrYWJsZUV4dHJhOjprYmwoYWxpZ24gPSAiYyIpICU+JQ0KICBrYWJsZV9wYXBlcigiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikNCmBgYA0KDQpXaGF0IHRvIGRvIHdpdGggdGhpcyBkYXRhIG5vdz8gRmlyc3QsIHdlIG5lZWQgdG8gbG9hZCBpdCBpbiBSIGFuZCBwcmVwYXJlIGZvciBhbmFseXNpcy4gVGhlIG51bWJlcnMgeW91IHNlZSBpbiB0aGUgb3V0cHV0IFIgcmVjb2duaXplcyAqKmFzIG51bWVyaWMqKi4gSW4gb3JkZXIgdG8gY29uZHVjdCBzdGF0aXN0aWNhbCBtb2RlbGluZyBhbmQgcHJvcGVybHkgdmlzdWFsaXplIG91ciByZXN1bHRzLCB3ZSBuZWVkIHRvIGNvbnZlcnQgb3VyIGRhdGEgdG8gKiphIGZhY3RvciBjbGFzcy4qKg0KDQpBIGZhY3RvciAob3IgY29kaW5nIHZhcmlhYmxlKSByZXByZXNlbnRzIGRpZmZlcmVudCBncm91cHMgb2YgZGF0YSBieSB1c2luZyBudW1iZXJzIChpbnRlZ2VycykuIEluIGZhY3QsIGZhY3RvcnMgYXBwZWFyIGFzIG51bWVyaWMgdmFyaWFibGVzLCBidXQgdGhleSBob2xkIG1lYW5pbmcgb2YgbGFiZWxzL25hbWVzIG9mIGRhdGEgZ3JvdXBzLCBpLmUuIG5vbWluYWwgdmFyaWFibGUuIFRoZXNlIGRhdGEgZ3JvdXBzIGFyZSByZXByZXNlbnRlZCBpbiBhIGZvcm0gb2YgJ2xldmVscycuICANCkluIG91ciBjYXNlLCBvdXIgbXVsdGlwbGUgY2hvaWNlIHF1ZXN0aW9uIG91dHB1dCB3aWxsIGNvbnRhaW4gNCBkYXRhIGdyb3VwcyAoJ0dyb2NlcnkgU3RvcmUnLCAnT25saW5lIHNob3AnLCAnU3BlY2lhbGlzZWQgY29mZmVlIHNob3AnLCAnb3RoZXInKSBhZnRlciBjb252ZXJ0aW5nIGl0IHRvIGZhY3RvcjoNCg0KYGBge3IsIGV2YWw9VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgQ29udmVydCBudW1lcmljIHZhbHVlIHRvIGZhY3RvcnMNCnF1YWx0cmljcyQnSW4gYSB0eXBpY2FsIHdlZWssIGhvdyBtYW55IGhvdXJzIGRvIHlvdSBzcGVuZCB3YXRjaGluZyBtb3ZpZXMgb3IgVFYgc2VyaWVzIG9uIE5ldGZsaXg/JyA8LSBmYWN0b3IocXVhbHRyaWNzJCdJbiBhIHR5cGljYWwgd2VlaywgaG93IG1hbnkgaG91cnMgZG8geW91IHNwZW5kIHdhdGNoaW5nIG1vdmllcyBvciBUViBzZXJpZXMgb24gTmV0ZmxpeD8nLCBsZXZlbHMgPSBjKDE6NSksIGxhYmVscyA9IGMoJ05ldmVyJywnMS0yIGhvdXJzJywnMy00IGhvdXJzJywnNS02IGhvdXJzJywnbW9yZSB0aGFuIDYgaG91cnMnKSkNCg0KcXVhbHRyaWNzJGAgU2VsZWN0ZWQgQ2hvaWNlXzFgIDwtIGZhY3RvcihxdWFsdHJpY3MkYCBTZWxlY3RlZCBDaG9pY2VfMWAsbGV2ZWxzID0gYygxOjIpLGxhYmVscyA9IGMoIk1hbGUiLCJGZW1hbGUiKSkNCg0KcXVhbHRyaWNzJGAgU2VsZWN0ZWQgQ2hvaWNlYCA8LSBmYWN0b3IocXVhbHRyaWNzJGAgU2VsZWN0ZWQgQ2hvaWNlYCwgbGV2ZWxzID0gYygxOjIpLCBsYWJlbHM9YygiQXVzdHJpYSIsIkdlcm1hbnkiKSkNCg0KDQojIFRhYmxlDQp0YWJsZShxdWFsdHJpY3MkJ0luIGEgdHlwaWNhbCB3ZWVrLCBob3cgbWFueSBob3VycyBkbyB5b3Ugc3BlbmQgd2F0Y2hpbmcgbW92aWVzIG9yIFRWIHNlcmllcyBvbiBOZXRmbGl4PycpDQp0YWJsZShxdWFsdHJpY3MkYCBTZWxlY3RlZCBDaG9pY2VgKSAgICAgI2NvdW50cmllcw0KdGFibGUocXVhbHRyaWNzJGAgU2VsZWN0ZWQgQ2hvaWNlXzFgKSAgICNnZW5kZXINCg0KYGBgDQoNClNlY29uZCwgeW91IG1pZ2h0IHdhbnQgdG8gdmlzdWFsaXplIHlvdXIgcmVzdWx0cy4gSW4gb3JkZXIgdG8gZG8gc28sIHRoZSBkYXRhIGZvcm1hdCBuZWVkcyB0byBiZSBpbiB0aGUgYXBwcm9wcmlhdGUgZm9ybWF0LkhlcmUgd2UgcHJvY2VlZCB3aXRoIGRhdGEgZm9ybWF0IGFkYXB0YXRpb24gZnJvbSB0aGUgcG9pbnQgd2hlcmUgd2Ugc3RvcHBlZDoNCg0KYGBge3IsIGV2YWw9VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgQ29udmVydGluZyBsb25nIGZvcm1hdCB0byB0aGUgdmlzdWFsaXNhdGlvbi1mcmllbmRseSBmb3JtYXQNCm1sY192aXN1YWxpc2F0aW9uIDwtIGFzLmRhdGEuZnJhbWUodGFibGUocXVhbHRyaWNzJCdJbiBhIHR5cGljYWwgd2VlaywgaG93IG1hbnkgaG91cnMgZG8geW91IHNwZW5kIHdhdGNoaW5nIG1vdmllcyBvciBUViBzZXJpZXMgb24gTmV0ZmxpeD8nKSkNCg0KIyBOYW1pbmcgY29sdW1ucw0KbmFtZXMobWxjX3Zpc3VhbGlzYXRpb24pIDwtIGMoJ1RpbWUnLCdDb3VudCcpDQoNCiMgT2JzZXJ2aW5nDQprbml0cjo6a2FibGUobWxjX3Zpc3VhbGlzYXRpb24pDQoNCmBgYA0KDQpUaGUgc2ltcGxlc3Qgd2F5IHRvIHZpc3VhbGl6ZSBkYXRhIG9idGFpbmVkIGZyb20gbXVsdGlwbGUgY2hvaWNlIHF1ZXN0aW9uIHdpdGggYSBzaW5nbGUgYW5zd2VyIGlzICoqYSBiYXIgY2hhcnQqKjoNCg0KYGBge3J9DQojIyBCYXNpYyBiYXIgY2hhcnQNCmxhYmVscyA8LSBhcy5jaGFyYWN0ZXIobWxjX3Zpc3VhbGlzYXRpb24kVGltZSkgI1NhdmUgbGFiZWxzIGZvciB4LWF4aXMgaW4gdGhlIGJhcnBsb3QNCmJhcnBsb3QobWxjX3Zpc3VhbGlzYXRpb24kQ291bnQsICMgQ29sdW1uIHRvIHZpc3VhbGl6ZQ0KICAgICAgICB4bGFiPSdUaW1lJywgIyBYLWF4aXMgbGFiZWwNCiAgICAgICAgeWxhYiA9ICdDb3VudChhbnN3ZXJzKScsICMgWS1heGlzIGxhYmVsDQogICAgICAgIG5hbWVzLmFyZyA9IGxhYmVscywNCiAgICAgICAgbWFpbiA9ICdIb3cgbWFueSBob3VycyBkbyB5b3Ugc3BlbmQgd2F0Y2hpbmcgbW92aWVzIG9yIHNlcmllcyBvbiBOZXRmbGl4PycpICMgVGl0bGUNCmBgYA0KDQpSIHBhY2thZ2UgKipnZ3Bsb3QyKiogYWxsb3dzIHlvdSB0byBjcmVhdGUgdmlzdWFsbHkgYXBwZWFsaW5nIGdyYXBoczoNCg0KYGBge3J9DQojIyBnZ3Bsb3QyIGJhciBjaGFydA0KbGlicmFyeShnZ3Bsb3QyKQ0KcCA8LSBnZ3Bsb3QoZGF0YT1tbGNfdmlzdWFsaXNhdGlvbiwgDQogICAgICAgICAgICAgYWVzKHg9VGltZSwgeT1Db3VudCwgZmlsbD1UaW1lKSkgKw0KICAgICAgICAgICAgIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5JykgKyB0aGVtZV9taW5pbWFsKCkgKyBsYWJzKHRpdGxlID0gIkluIGEgdHlwaWNhbCB3ZWVrLCBob3cgbWFueSBob3VycyBkbyB5b3Ugc3BlbmQgd2F0Y2hpbmcgbW92aWVzIG9yIHNlcmllcyBvbiBOZXRmbGl4PyIpDQpwDQpgYGANCg0KQW5vdGhlciBSIGxpYnJhcnkgd2hpY2ggY2FuIGhlbHAgeW91IG1ha2UgYW1hemluZyBpbnRlcmFjdGl2ZSBjaGFydHMgaW4gYSBtaW51dGUgaXMgKipwbG90bHkqKi4gSGVyZSB3ZSB1c2UgYSBmdW5jdGlvbiBjYWxsZWQgKipnZ3Bsb3RseSgpKiosIHdoaWNoIGFsbG93cyB5b3UgdG8gdHVybiBhbnkgKipnZ3Bsb3QyKiogY2hhcnQgaW50ZXJhY3RpdmUuIFNpbmNlIHdlIGhhdmUgYWxyZWFkeSBjcmVhdGVkIGEgYmFyIGNoYXJ0IHVzaW5nIGdncGxvdDIgYW5kIHNhdmVkIGl0IGFzICJwIiwgd2Ugd2lsbCBqdXN0IHR1cm4gaXQgaW50byBwbG90bHkgZ3JhcGg6DQoNCmBgYHtyLHdhcm5pbmc9RixtZXNzYWdlPUZ9DQojIyBnZ3Bsb3RseSBiYXIgY2hhcnQNCg0KbGlicmFyeShwbG90bHkpDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCg0KQW4gaW1wcm92ZWQgdmVyc2lvbiBvZiBnZ3Bsb3QyIHBhY2thZ2UgaXMgdGhlIHBhY2thZ2VkIGNhbGxlZCAqKmdndmlzKiosIHdoaWNoIGlzIHN0aWxsIGluIGRldmVsb3Bpbmc6DQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMjIGdndmlzIGJhciBjaGFydA0KDQpsaWJyYXJ5KGdndmlzKQ0KZ2d2aXMobWxjX3Zpc3VhbGlzYXRpb24sIA0KICAgICAgeCA9IH5UaW1lLCANCiAgICAgIHkgPSB+Q291bnQsIA0KICAgICAgZmlsbD1+VGltZSkNCmBgYA0KDQoNCg0KRGF0YSB0eXBlIGNvbGxlY3RlZCBmcm9tIHRoZSBwcmV2aW91cyBxdWVzdGlvbiBpcyBvcmRpbmFsIGFzIHdlIGFyZSBhYmxlIHRvIG1ha2UgYSBuYXR1cmFsIG9yZGVyIG9mIHRoZSBsZXZlbHMuIFNpbmNlIGl0IGlzIG9yZGluYWwgZGF0YSB0eXBlLCBpdCBiZWxvbmdzIHRvIGNhdGVnb3JpY2FsIGRhdGEuIEZvciB0aGUgYW5hbHlzaXMgb2YgY2F0ZWdvcmljYWwgZGF0YSB3ZSBjYW4gdXNlIENoaS1zcXVhcmUgdGVzdCBvciBGaXNoZXIncyB0ZXN0IGlmIGEgY291bnQgZm9yIHNvbWUgbGV2ZWwgaXMgbGVzcyB0aGFuIDUuIA0KDQojIyMjIEZpc2NoZXIncyBleGFjdCB7LX0NCg0KRmlzaGVyJ3MgZXhhY3QgdGVzdCBpcyB1c2VkIHRvIHRlc3QgYSBoeXBvdGhlc2lzIHdpdGggZGF0YSBvYnRhaW5lZCBmcm9tIG11bHRpcGxlIGNob2ljZSBxdWVzdGlvbnMgd2l0aCBzaW5nbGUgYW5zd2VyLiBSZXN1bHRzIGZyb20gbXVsdGlwbGUgY2hvaWNlIHF1ZXN0aW9ucyB3aXRoIG11bHRpcGxlIGFuc3dlcnMgYXJlIHRyZWF0ZWQgd2l0aCBkaWZmZXJlbnQgdGVzdC4NCjx1bD48bGk+IDxCPiBBcHBsaWNhdGlvbjogPC9CPiB3aGVuIHlvdSBoYXZlIDxCPiAxIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgIDEgaW5kZXBlbmRlbnQgdmFyaWFibGUgd2l0aCAyIG9yIG1vcmUgbGV2ZWxzL2ZhY3RvcnMgPC9CPjwvdWw+PC9saT4NCjx1bD48bGk+IFVzZWQgd2hlbiBmcmVxdWVuY3kgaW4gYXQgbGVhc3Qgb25lIGNlbGwgaXMgPEI+IGxlc3MgdGhhbiA1IDwvQj4uIFdoZW4gZnJlcXVlbmNpZXMgaW4gZWFjaCBjZWxsIGFyZSBncmVhdGVyIHRoYW4gNSwgQ2hpLXNxdWFyZSB0ZXN0IHNob3VsZCBiZSB1c2VkLjwvdWw+PC9saT4NCjx1bD48bGk+IDxCPkh5cG90aGVzaXM6PC9CPiBJcyB0aGVyZSBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gZnJlcXVlbmNpZXMgYmV0d2VlbiB2YWx1ZXMgb2JzZXJ2ZWQgaW4gY2VsbHMgYW5kIHZhbHVlcyBleHBlY3RlZCBpbiBjZWxscyA/IChSIGZvciBNYXJrZXRpbmcgYW5kIFJlc2VhcmNoIEFuYWx5dGljcyk8L3VsPjwvbGk+DQo8dWw+PGxpPiA8Qj5IMDo8L0I+IFRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB0d28gY2F0ZWdvcmljYWwgdmFyaWFibGVzLlRoZXJlZm9yZSwgdHdvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhcmUgPEI+IGluZGVwZW5kZW50LjwvQj4gS25vd2luZyB0aGUgdmFsdWUgb2Ygb25lIHZhcmlhYmxlIGRvZXMgbm90IGhlbHAgdG8gcHJlZGljdCB0aGUgdmFsdWUgb2YgdGhlIG90aGVyIHZhcmlhYmxlLjwvdWw+PC9saT4NCjx1bD48bGk+IDxCPkgxOjwvQj4gVGhlcmUgaXMgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcy5UaGVyZWZvcmUsIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYXJlIDxCPiBkZXBlbmRlbnQuPC9CPktub3dpbmcgdGhlIHZhbHVlIG9mIG9uZSB2YXJpYWJsZSBoZWxwcyB0byBwcmVkaWN0IHRoZSB2YWx1ZSBvZiB0aGUgb3RoZXIgdmFyaWFibGUuPC91bD48L2xpPg0KPHVsPjxsaT4gVXN1YWxseSwgdGhpcyB0eXBlIG9mIHRlc3QgaXMgdXNlZCBvbiAyeDIgY29udGluZ2VuY3kgdGFibGVzLiBIb3dldmVyLCBpdCBjYW4gYmUgYXBwbGljYWJsZSBvbiBjb250aW5nZW5jeSB0YWJsZXMgb2YgbGFyZ2VyIGRpbWVuc2lvbnMuPC91bD48L2xpPg0KDQo8Qj5FeGFtcGxlOjwvQj4gV2Ugd291bGQgbGlrZSB0byBrbm93IHdoZXRoZXIgYSBudW1iZXIgb2YgaG91cnMgc3BlbnQgd2F0Y2hpbmcgTmV0ZmxpeCBkZXBlbmRzIG9uIHRoZSByZXNwb25kZW50cycgY291bnRyeSBvZiBvcmlnaW4uDQoNCg0KYGBge3J9DQojIENyZWF0aW9uIG9mIGNvbnRpbmdlbmN5IHRhYmxlDQpmaXNoZXJfdGVzdF90YWJsZSA8LXRhYmxlKHF1YWx0cmljcyRgIFNlbGVjdGVkIENob2ljZWAscXVhbHRyaWNzJCdJbiBhIHR5cGljYWwgd2VlaywgaG93IG1hbnkgaG91cnMgZG8geW91IHNwZW5kIHdhdGNoaW5nIG1vdmllcyBvciBUViBzZXJpZXMgb24gTmV0ZmxpeD8nKQ0KIyBDaGVjayBob3cgb3VyIGNvbnRpZ2VuY3kgdGFibGUgbG9va3MgbGlrZQ0KZmlzaGVyX3Rlc3RfdGFibGUNCg0KIyBTaW5jZSB3ZSBoYXZlIGEgY291bnQgbGVzcyB0aGFuIDUsIHdlIHNob3VsZCBhcHBseSBGaXNoZXIncyB0ZXN0IGluc3RlYWQgb2YgQ2hpLXNxdWFyZS4NCg0KIyBGaXNoZXIncyB0ZXN0DQp0ZXN0IDwtIGZpc2hlci50ZXN0KGZpc2hlcl90ZXN0X3RhYmxlKQ0KdGVzdA0KDQojIHAtdmFsdWUNCnRlc3QkcC52YWx1ZQ0KYGBgDQoNCkZyb20gdGhlIG91dHB1dCBhbmQgZnJvbSB0ZXN0JHAudmFsdWUgd2Ugc2VlIHRoYXQgdGhlIHAtdmFsdWUgaXMgaGlnaGVyIHRoYW4gdGhlIHNpZ25pZmljYW5jZSBsZXZlbCBvZiA1JS4gTGlrZSBhbnkgb3RoZXIgc3RhdGlzdGljYWwgdGVzdCwgaWYgdGhlIHAtdmFsdWUgaXMgaGlnaGVyIHRoYW4gdGhlIHNpZ25pZmljYW5jZSBsZXZlbCwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4NCg0KSW4gb3VyIGNhc2UsIG5vdCByZWplY3RpbmcgdGhlIG51bGwgaHlwb3RoZXNpcyBmb3IgdGhlIEZpc2hlcuKAmXMgZXhhY3QgdGVzdCBvZiBpbmRlcGVuZGVuY2UgbWVhbnMgdGhhdCB0aGVyZSBpcyBubyBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gVGhlcmVmb3JlLCBrbm93aW5nIHRoZSB2YWx1ZSBvZiBvbmUgdmFyaWFibGUgZG9lcyBub3QgaGVscCB0byBwcmVkaWN0IHRoZSB2YWx1ZSBvZiB0aGUgb3RoZXIgdmFyaWFibGUuDQoNCiMjIyMgQ2hpLXNxdWFyZSB0ZXN0OiBHb29kbmVzcyBvZiBmaXQgJiBJbmRlcGVuZGVuY2UgdGVzdCB7LX0NCg0KMSkgR29vZG5lc3Mgb2YgZml0DQo8ZGl2Pjx1bD48bGk+PEI+IEFwcGxpY2F0aW9uOiA8L0I+d2hlbiB5b3Ugb25seSBoYXZlIDxCPiAxIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgbm9uZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgPC9CPjwvdWw+PC9saT4NCjx1bD48bGk+IDxCPiBIeXBvdGhlc2lzOjwvQj4gSXMgdGhlcmUgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIGZyZXF1ZW5jaWVzIGJldHdlZW4gdmFsdWVzIG9ic2VydmVkIGluIGNlbGxzIGFuZCB2YWx1ZXMgZXhwZWN0ZWQgaW4gY2VsbHMgPyA8L3VsPjwvbGk+DQo8dWw+PGxpPiA8Qj4gSDA6IDwvQj4gVGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBvYnNlcnZlZCBhbmQgdGhlIGV4cGVjdGVkIGZyZXF1ZW5jaWVzLjwvdWw+PC9saT4NCjx1bD48bGk+IDxCPiBIMTogPC9CPiBUaGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgb2JzZXJ2ZWQgYW5kIHRoZSBleHBlY3RlZCBmcmVxdWVuY2llcy4gPC91bD48L2xpPg0KPHVsPjxsaT4gSWYgd2UgZG9uJ3Qgc3BlY2lmeSBleHBlY3RlZCBmcmVxdWVuY3kgcGVyIGNlbGwgKHNlZSBpbiB0aGUgY29kZSBiZWxvdyksIHRoZW4gaXQgaXMgZXhwZWN0ZWQgdGhhdCBhbGwgY2VsbHMgc2hvdyBhbiBlcWF1bCBmcmVxdWVuY3kuIDwvdWw+PC9saT4NCjx1bD48bGk+IDxCPiBFeGFtcGxlPC9CPiA6J0RvIHRoZSBudW1iZXJzIG9mIHJlc3BvbmRlbnRzIHdobyBhcmUgc3BlbmRpbmcgZGlmZmVyZW50IGFtb3VudCBvZiBob3VycyB3YXRjaGluZyBOZXRmbGl4IDxCPiBzaWduaWZpY2FudGx5IGRpZmZlciBmcm9tIGVhY2ggb3RoZXI/PC9CPic8L3VsPjwvbGk+PC9kaXY+DQo8dWw+PGxpPjxCPiBOb3RlIHRoYXQgd2UgZGlkIG5vdCBhc3N1bWUgYW55IHNwZWNpZmljIGRpc3RyaWJ1dGlvbiwgc28gd2UgYXJlIGFzc3VtaW5nIHRoYXQgZWFjaCBjb3VudCB3aWxsIGhhdmUgdGhlIHNhbWUgb3Igc2ltaWxhciBudW1iZXIuIDwvdWw+PC9saT48L0I+DQoNCmBgYHtyfSANCiMgQ3JlYXRpbmcgdGFibGUgDQoobWxjX2NoaV9zcXVhcmUgPC0gdGFibGUocXVhbHRyaWNzJCdJbiBhIHR5cGljYWwgd2VlaywgaG93IG1hbnkgaG91cnMgZG8geW91IHNwZW5kIHdhdGNoaW5nIG1vdmllcyBvciBUViBzZXJpZXMgb24gTmV0ZmxpeD8nKSkNCiAgICAgIA0KIyBDaGktc3F1YXJlIHRlc3QgKHdpdGhvdXQgZ2l2ZW4gZXhwZWN0ZWQgdmFsdWVzID0gZXF1YWwgdmFsdWVzICkNCmNoaXNxLnRlc3QobWxjX2NoaV9zcXVhcmUpDQpgYGANCg0KVGhlIHAtdmFsdWUgb2YgdGhlIHRlc3QgaXMgaGlnaGVyIHRoYW4gMC4wNS4gV2UgY2FuIGNvbmNsdWRlIHRoYXQgdGhlIG51bWJlcnMgb2YgcmVzcG9uZGVudHMgd2hvIHNwZW50IGRpZmZlcmVudCBhbW91bnQgb2YgaG91cnMgd2F0Y2hpbmcgTmV0ZmxpeCBhcmUgY29tbW9ubHkgZGlzdHJpYnV0ZWQuIE9ic2VydmVkIGRpc3RyaWJ1dGlvbiBkb2VzIG5vdCBkaWZmZXIgc2lnbmlmaWNhbnRseSBmcm9tIHRoZSBleHBlY3RlZC4gVGhpcyByZXN1bHQgZG9lcyBub3Qgc3VycHJpc2UgaWYgeW91IHRha2UgYSBsb29rIGF0IHRoZSB2YWx1ZXMgZm9yIGVhY2ggbGV2ZWwgaW4gdGhlIHRhYmxlIHdlIGNyZWF0ZWQgYmVmb3JlIGNvbmR1Y3RpbmcgdGhlIHRlc3QuIFRoZXJlIHlvdSBjYW4gc2VlIHRoYXQgY291bnQgb2YgYW5zd2VycyBpbiBlYWNoIGxldmVsIGlzIG1vcmUgb3IgbGVzcyBub3QgZGV2aWF0aW5nIHRvbyBtdWNoLiBJdCBpcyB2aXNpYmxlIGlmIHlvdSB0YWtlIGEgbG9vayBhdCB0aGUgcHJldmlvdXMgdmlzdWFsaXNhdGlvbnMgYXMgd2VsbC4NCg0KDQpJZiB3ZSBhcmUgaW50ZXJlc3RlZCBpbiB0ZXN0aW5nIG1vcmUgc3BlY2lmaWMgZGlzdHJpYnV0aW9uLCBpLmUuIGV4cGVjdCB0aGF0IDQwJSBvZiBvdXIgcmVzcG9uZGVudHMgYXJlIHdhdGNoaW5nIE5ldGZsaXggMy00IGhvdXJzLCB3ZSBjYW4gaW50cm9kdWNlIGNvcnJlc3BvbmRpbmcgZGlzdHJpYnV0aW9uIGluIHRoZSB0ZXN0LiANCg0KYGBge3J9DQojIEV4cGVjdGVkIHZhbHVlcyBpbiBwZXJjZW50YWdlcyBmb3IgZWFjaCBhbHRlcm5hdGl2ZS4gVGhlIHN1bSBtdXN0IGJlIDEuDQpleHBlY3RlZF92YWx1ZXMgPC0gYygwLjEwLCAjIFdlIGV4cGVjdCB0aGF0IDEwJSBvZiBvdXIgcmVzcG9uZGVudHMgZG8gbm90IHdhdGNoIE5ldGZsaXggYXQgYWxsICgiTmV2ZXIiKS4NCiAgICAgICAgICAgICAgICAgICAgIDAuMjAsICMgV2UgZXhwZWN0IHRoYXQgMjAlIG9mIG91ciByZXNwb25kZW50cyB3YXRjaCBOZXRmbGl4IDEtMiBob3VycyBhIHdlZWsuICANCiAgICAgICAgICAgICAgICAgICAgIDAuNDAsICMgV2UgZXhwZWN0IHRoYXQgNDAlIG9mIG91ciByZXNwb25kZW50cyB3YXRjaCBOZXRmbGl4IDMtNCBob3VycyBhIHdlZWsuDQogICAgICAgICAgICAgICAgICAgICAwLjIwLCAjIFdlIGV4cGVjdCB0aGF0IDIwJSBvZiBvdXIgcmVzcG9uZGVudHMgd2F0Y2ggTmV0ZmxpeCA1LTYgaG91cnMgYSB3ZWVrLg0KICAgICAgICAgICAgICAgICAgICAgMC4xMCAjIFdlIGV4cGVjdCB0aGF0IDEwJSBvZiBvdXIgcmVzcG9uZGVudHMgd2F0Y2ggTmV0ZmxpeCBtb3JlIHRoYW4gNiBob3VycyBhIHdlZWsuDQogICAgICAgICAgICAgICAgICAgICkNCiMgQ2hpLXNxdWFyZSB0ZXN0IHdpdGggZXhwZWN0ZWQgdmFsdWVzDQpjaGlzcS50ZXN0KG1sY19jaGlfc3F1YXJlLCBwPWV4cGVjdGVkX3ZhbHVlcykNCmBgYA0KDQpUaGlzIHRpbWUgdGhlIHAtdmFsdWUgb2YgdGhlIHRlc3QgaXMgbG93ZXIgdGhhbiAwLjA1LldlIGhhdmUgYW4gZXZpZGVuY2UgdGhhdCBvYnNlcnZlZCBkaXN0cmlidXRpb24gZG9lcyBzaWduaWZpY2FudGx5IGRpZmZlciBmcm9tIHRoZSBleHBlY3RlZCBkaXN0cmlidXRpb24gKDEwJS8yMCUvNDAlLzIwJS8xMCUpLiAgDQoNCg0KMikgQ2hpLVNxdWFyZSBUZXN0IG9mIEluZGVwZW5kZW5jZQ0KPGRpdj48dWw+PGxpPiA8Qj4gQXBwbGljYXRpb246IDwvQj53aGVuIHlvdSBoYXZlIDxCPiAxIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgIDEgaW5kZXBlbmRlbnQgdmFyaWFibGUgd2l0aCAyIG9yIG1vcmUgbGV2ZWxzL2ZhY3RvcnMgPC9CPjwvdWw+PC9saT4gDQo8dWw+PGxpPiA8Qj4gSHlwb3RoZXNpczogPC9CPiBJcyB0aGVyZSBhbiBhc3NvY2lhdGlvbiBiZXR3ZWVuIGNhdGVnb3JpY2FsIHZhcmlhYmxlIFggYW5kIGNhdGVnb3JpY2FsIHZhcmlhYmxlIFk/IDwvdWw+PC9saT4NCjx1bD48bGk+IDxCPiBIMDogPC9CPiBUaGVyZSBpcyBubyBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzLjwvQj48L3VsPjwvbGk+DQo8dWw+PGxpPiA8Qj4gSDE6IDwvQj4gVGhlcmUgaXMgYW4gYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcy48L0I+PC91bD48L2xpPg0KPHVsPjxsaT4gPEI+IEV4YW1wbGU6IDwvQj4gSXMgdGhlcmUgYW4gYXNzb2NpYXRpb24gYmV0d2VlbiBnZW5kZXIgYW5kIHRoZSBob3VycyBzcGVudCB3YXRjaGluZyBOZWZsaXggZHVyaW5nIGEgd2Vlaz8gPC91bD48L2xpPjwvZGl2Pg0KDQpgYGB7cn0NCiMgQ3JlYXRpb24gb2YgY29udGluZ2VuY3kgdGFibGUNCmNoaV9zcXVhcmVfdGFibGUgPC10YWJsZShxdWFsdHJpY3MkYCBTZWxlY3RlZCBDaG9pY2VfMWAscXVhbHRyaWNzJCdJbiBhIHR5cGljYWwgd2VlaywgaG93IG1hbnkgaG91cnMgZG8geW91IHNwZW5kIHdhdGNoaW5nIG1vdmllcyBvciBUViBzZXJpZXMgb24gTmV0ZmxpeD8nKQ0KDQojIENoaS1zcXVhcmUgaW5kZXBlbmRlbmNlIHRlc3QNCmNoaXNxLnRlc3QoY2hpX3NxdWFyZV90YWJsZSkNCmBgYA0KDQpTaW5jZSB0aGUgcC12YWx1ZSAoMC44MTM1KSBpcyBoaWdoZXIgdGhhbiB0aGUgc2lnbmlmaWNhbmNlIGxldmVsICgwLjA1KSwgd2UgY2Fubm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaHVzLCB3ZSBjb25jbHVkZSB0aGF0IHRoZXJlIGlzIG5vIGFzc29jaWF0aW9uIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGdlbmRlciBhbmQgbnVtYmVyIG9mIGhvdXJzIHNwZW50IHdhdGNoaW5nIE5ldGZsaXguIFRoZXJlZm9yZSwgd2UgY2FuIHNheSB0aGF0IHRoZSBob3VycyBzcGVudCBpcyBpbmRlcGVuZGVudCBmcm9tIHRoZSBnZW5kZXIgb2YgcGFydGljaXBhbnQuDQoNCiMjIyBNdWx0aXBsZSBjaG9pY2Ugd2l0aCBtdWx0aXBsZSBhbnN3ZXJzDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnbXVsdGlwbGUtY2hvaWNlLXF1ZXN0aW9uLW11bHRpcGxlLWFuc3dlcnMucG5nJykNCmBgYA0KDQpCZWZvcmUgd2UgY29uZHVjdCBhbnkgdGVzdCwgd2Ugd2lsbCBkbyBzb21lIHNpbXBsZSBjYWxjdWxhdGlvbnMgYW5kIHZpc3VhbGlzZSBvdXIgZGF0YS4gDQoNCmBgYHtyfQ0KIyBSZW5hbWUgY29sdW1ucw0KY29sbmFtZXMocXVhbHRyaWNzKVszOF0gPC0gImphIU5hdHVybGljaCINCmNvbG5hbWVzKHF1YWx0cmljcylbMzldIDwtICJDbGV2ZXIiDQpjb2xuYW1lcyhxdWFsdHJpY3MpWzQwXSA8LSAiU3BhciBWaXRhbCINCmNvbG5hbWVzKHF1YWx0cmljcylbNDFdIDwtICIuLi4iDQoNCiMgUmVwbGFjaW5nIE5BIHdpdGggMA0KcXVhbHRyaWNzJGBqYSFOYXR1cmxpY2hgW2lzLm5hKHF1YWx0cmljcyRgamEhTmF0dXJsaWNoYCldPTANCnF1YWx0cmljcyRDbGV2ZXJbaXMubmEocXVhbHRyaWNzJENsZXZlcildPTANCnF1YWx0cmljcyRgU3BhciBWaXRhbGBbaXMubmEocXVhbHRyaWNzJGBTcGFyIFZpdGFsYCldPTANCnF1YWx0cmljcyQuLi5baXMubmEocXVhbHRyaWNzJC4uLildPTANCg0KIyBDYWxjdWxhdGluZyBmcmVxdWVuY3ksIHBlcmNlbnRhZ2Ugb2YgcmVzcG9uZGVudHMgYW5kIHBlcmNlbnRhZ2Ugb2YgY2FzZXMNCmRmLmNvY2hyYW4gPC0gZGF0YS5mcmFtZShGcmVxdW5lY3kgPSBjb2xTdW1zKHF1YWx0cmljc1szODo0MV0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgIFNoYXJlX29mX3Jlc3BvbmRlbnRzID0gKGNvbFN1bXMocXVhbHRyaWNzWzM4OjQxXSkvc3VtKHF1YWx0cmljc1szODo0MV0pKSoxMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNoYXJlX29mX2Nhc2VzID0oKGNvbFN1bXMocXVhbHRyaWNzWzM4OjQxXSkpL25yb3cocXVhbHRyaWNzWzM4OjQxXSkpKjEwMCkNCiMgT2JzZXJ2aW5nDQpkZi5jb2NocmFuDQoNCiMgVmlzdWFsaXNhdGlvbg0KYmFycGxvdChkZi5jb2NocmFuWywzXSwgbmFtZXMuYXJnID0gcm93Lm5hbWVzKGRmLmNvY2hyYW4pLCBtYWluID0gIiUgb2YgUmVzcG9uZGVudHMgZmFtaWxpYXIgd2l0aCBicmFuZHMiLCB4bGFiID0gIkJyYW5kIix5bGFiID0gIlBlcmNlbnRhZ2UiKQ0KYGBgDQoNClRoZSB2aXN1YWxpc2F0aW9uIGFib3ZlIGRlcGljdHMgdGhlIGZhY3QgdGhhdCBtb3JlIHRoYW4gNjAlIHBlcmNlbnQgb2YgcGVvcGxlIGFyZSBmYW1pbGlhciB3aXRoIHRoZSBicmFuZCAiamEhTmF0dXJsaWNoIiwgd2hpbGUgd2UgY2FuIG5vdCBzYXkgdGhlIHNhbWUgZm9yIG90aGVyIGJyYW5kcyBjb25zaWRlcmVkIGluIG91ciBxdWVzdGlvbi4gDQoNCg0KRm9yIHRoZSBhbmFseXNpcyBvZiByZXN1bHRzIGNvbGxlY3RlZCB3aXRoIG11bHRpcGxlIGNob2ljZSBxdWVzdGlvbiB3aXRoIG11bHRpcGxlIHBvc3NpYmxlIGFuc3dlcnMsIHdlIGNhbiB1c2UgKipDb2NocmFuJ3MgUSB0ZXN0LioqQWx0aG91Z2ggd2UgZGlkIG5vdCBtZW50aW9uIGl0IGJlZm9yZSwgaXQgaXMgbm90IHRvbyBkaWZmZXJlbnQgZnJvbSB3aGF0IHlvdSBoYXZlIGFscmVhZHkgbGVhcm5lZCBhYm91dCBvdGhlciB0ZXN0cy4gDQoNClRoZSBDb2NocmFu4oCZcyBRIHRlc3QgYW5kIGFzc29jaWF0ZWQgbXVsdGlwbGUgY29tcGFyaXNvbnMgcmVxdWlyZSB0aGUgZm9sbG93aW5nIGFzc3VtcHRpb25zOg0KMS4gUmVzcG9uc2VzIGFyZSBkaWNob3RvbW91cyBhbmQgZnJvbSBrIG51bWJlciBvZiBtYXRjaGVkIHNhbXBsZXMuDQoyLiBUaGUgc3ViamVjdHMgYXJlIGluZGVwZW5kZW50IG9mIG9uZSBhbm90aGVyIGFuZCB3ZXJlIHNlbGVjdGVkIGF0IHJhbmRvbSBmcm9tIGEgbGFyZ2VyIHBvcHVsYXRpb24uDQozLiBUaGUgc2FtcGxlIHNpemUgaXMgc3VmZmljaWVudGx5IOKAnGxhcmdl4oCdLiAoQXMgYSBydWxlIG9mIHRodW1iLCB0aGUgbnVtYmVyIG9mIHN1YmplY3RzIGZvciB3aGljaCB0aGUNCnJlc3BvbnNlcyBhcmUgbm90IGFsbCAw4oCZcyBvciAx4oCZcywgbiwgc2hvdWxkIGJlIOKJpSA0IGFuZCBuayBzaG91bGQgYmUg4omlIDI0KQ0KDQpJbiBhIHdpdGhpbi1zdWJqZWN0cyBleHBlcmltZW50IGRlc2lnbiB3aXRoIHRocmVlIG9yIG1vcmUgb2JzZXJ2YXRpb25zIG9mIGEgZGljaG90b21vdXMoPSBqdXN0IHR3byBsZXZlbHMgc3VjaCBhcyAiWWVzIiBvciAiTm8iKSBjYXRlZ29yaWNhbCBvdXRjb21lLCB5b3UgdXRpbGl6ZSBDb2NocmFuJ3MgUSB0ZXN0IHRvIGFzc2VzcyBtYWluIGVmZmVjdHMuU2ltaWxhcmx5LCBpbiBvdXIgbXVsdGlwbGUgY2hvaWNlIHF1ZXN0aW9uIHdpdGggbXVsdGlwbGUgYW5zd2VycyB3ZSBoYXZlIHRoZSBzYW1lIHJlc3BvbmRlbnQgZ29pbmcgdGhyb3VnaCB0aHJlZSBvciBtb3JlIHBvdGVudGlhbCBhbnN3ZXJzIHdpdGggZGljaG90b21vdXMoPXllcyBvciBubykgY2F0ZWdvcmljYWwgb3V0Y29tZS4gDQoNCg0KYGBge3J9DQpsaWJyYXJ5KG5vbnBhcikNCg0KIyBDcmVhdGlvbiBvZiBtYXRyaXgNCiNtYXRyaXguY29jaHJhbiA8LSBjYmluZChxdWFsdHJpY3MkYGphIU5hdHVybGljaGAsDQojICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyRDbGV2ZXIsDQojICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyRgU3BhciBWaXRhbGAsDQojICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyRgLi4uYCkNCiMgVHVybmluZyBOQXMgdG8gMA0KI21hdHJpeC5jb2NocmFuW2lzLm5hKG1hdHJpeC5jb2NocmFuKV09MA0KDQojIENvY2hyYW4gdGVzdCAgICAgICAgICAgICAgICAgICANCiNjb2NocmFucy5xKG1hdHJpeC5jb2NocmFuLCBhbHBoYSA9IDAuMDUpDQoNCmBgYA0KDQpUaGUgcC12YWx1ZSBsZXNzIHRoYW4gMC4wNSBpbmRpY2F0ZXMgdGhhdCB0aGVyZSBpcyBlbm91Z2ggZXZpZGVuY2UgdG8gY29uY2x1ZGUgdGhhdCBzb21lIG9mIHRoZSBzdG9yZSBicmFuZHMgYXJlIGJldHRlciBrbm93biBhbW9uZyBvdXIgcmVzcG9uZGVudHMgdGhhbiBvdGhlci4gSW4gb3JkZXIgdG8gdGFrZSBhIGNsb3NlciBsb29rIGF0IGl0LCB3ZSBuZWVkIHRvIGNvbmR1Y3QgYSBwb3N0IGhvYyB0ZXN0Lg0KDQpgYGB7cn0NCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KbGlzdC5jb2NocmFuIDwtIGxpc3QocXVhbHRyaWNzJGBqYSFOYXR1cmxpY2hgLA0KICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyRDbGV2ZXIsDQogICAgICAgICAgICAgICAgICAgcXVhbHRyaWNzJGBTcGFyIFZpdGFsYCwNCiAgICAgICAgICAgICAgICAgICBxdWFsdHJpY3MkLi4uKSAjIGltYWdpbmFyeSBicmFuZA0KDQojIFJlcGxhY2luZyBOQXMgaW4gdGhlIGxpc3Qgd2l0aCAwIGluIG9yZGVyIHRvIGJlIGFibGUgdG8gcnVuIHRoZSB0ZXN0DQpsaXN0LmNvY2hyYW4gPC0gcmFwcGx5KGxpc3QuY29jaHJhbiwgZj1mdW5jdGlvbih4KSBpZmVsc2UoaXMubmEoeCksMCx4KSwgaG93PSJyZXBsYWNlIiApDQoNCiMgUG9zdCBob2MgdGVzdCAoRHVubiBUZXN0KQ0KRHVublRlc3QobGlzdC5jb2NocmFuLCBtZXRob2Q9ImJvbmZlcnJvbmkiKQ0KDQpgYGANCg0KRnJvbSB0aGUgcmVzdWx0cyBvZiB0aGUgRHVubiBUZXN0LCB3ZSBjYW4gc2VlIHRoYXQgdGhlcmUgaXMgYSBiaWcgZGlmZmVyZW5jZSBiZXR3ZWVuIDEgKCJqYSFOYXTDvHJsaWNoIikgYW5kIDQoIi4uLiIpLCBhcyB3ZWxsIGFzIGJldHdlZW4gNCgiLi4uIikgYW5kIDMoIlNwYXIgVml0YWwiKS4gDQoNCiMjIyBSYW5rIG9yZGVyIHF1ZXN0aW9uIHstfQ0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3Jhbmstb3JkZXItcXVlc3Rpb24ucG5nJykNCmBgYA0KDQpBIHJhbmsgb3JkZXIgcXVlc3Rpb24gYXNrcyByZXNwb25kZW50cyB0byBjb21wYXJlIGl0ZW1zIHRvIGVhY2ggb3RoZXIgYnkgcGxhY2luZyB0aGVtIGluIG9yZGVyIG9mIHByZWZlcmVuY2UuIE5vdGUgdGhhdCB0aGUgZGF0YSBvYnRhaW5lZCBmcm9tIGEgcmFuayBvcmRlciBxdWVzdGlvbiBzaG93cyBhbiBvcmRlciBvZiBhIHJlc3BvbmRlbnQncyBwZXJlZmVyZW5jZSwgYnV0IG5vdCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGl0ZW1zLiBGb3IgaW5zdGFuY2UsIGlmIHRoZSB0aGUgbW9zdCBpbXBvcnRhbnQgZmVhdHVyZSBvZiBhIGZpdG5lc3MgdHJhY2tlciBmb3IgYSByZXNwb25kZW5kdCBYWSBpcyAiTWVhc3VyaW5nIHN0ZXBzIiBhbmQgdGhlIHNlY29uZCBtb3N0IGltcG9ydGFudCBmZWF0dXJlICJDYWxvcmllcyBidXJuZWQiLCB3ZSBkb24ndCBrbm93IGZvciBob3cgbXVjaCBtb3JlIGltcG9ydGFudCBpcyB0aGUgZm9ybWVyIG9uZSBpbiBjb21wYXJpc29uIHRvIHRoZSBsYXR0ZXIgb25lLg0KDQpJbnR1aXRpdmUgcXVlc3Rpb24gdG8gYXNrIGlzIHRoZSBmb2xsb3dpbmc6IHdoaWNoIGZlYXR1cmUgb2YgdGhlIGZpdG5lc3MgdHJhY2tlciBpcyB0aGUgbW9zdCBpbXBvcnRhbnQgZm9yIG91ciByZXNwb25kZW50cz8NCg0KV2UgY2FuIGFuc3dlciB0aGlzIHF1ZXN0aW9uIGJ5IGNhbGN1bGF0aW5nIGEgbWVhbiByYW5rIGZvciBlYWNoIGZlYXR1cmUuIEJlZm9yZSB3ZSBkbyBzbywgd2Ugd2lsbCBjcmVhdGUgYSBzZXBhcmF0ZSBkYXRhIGZyYW1lIGFuZCBhZGQgY29sdW1ucyBvZiB0aGUgcmVzcG9uc2UgZGF0YS4NCmBgYHtyfQ0KcmFuay5kYXRhIDwtIGRhdGEuZnJhbWUocXVhbHRyaWNzJGAgTWVhc3VyaW5nIHN0ZXBzYCwNCiAgICAgICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyRgIENhbG9yaWVzIGJ1cm5lZGAsDQogICAgICAgICAgICAgICAgICAgICAgICBxdWFsdHJpY3MkYCBNZWFzdXJpbmcgaGVhcnRiZWF0YCwNCiAgICAgICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyRgIEV4ZXJjaXNlIHRyYWNraW5nYCwNCiAgICAgICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyRgIE1lYXN1cmluZyBkaXN0YW5jZWApDQpjb2xuYW1lcyhyYW5rLmRhdGEpPC1jKCJNZWFzdXJpbmcgc3RlcHMiLCJDYWxvcmllcyBidXJuZWQiLCJNZWFzdXJpbmcgaGVhcnRiZWF0IiwiRXhlcmNpc2UgdHJhY2tpbmciLCJNZWFzdXJpbmcgZGlzdGFuY2UiKQ0KDQpgYGANCg0KRmlyc3QgaW5mb3JtYXRpb24gd2Ugd291bGQgbGlrZSB0byBrbm93IGlzIGhvdyBtYW55IHByZWZlcmVuY2UgY29tYmluYXRpb25zIHRoZXJlIGFyZSwgYW5kIGhvdyByZXBldGl0aXZlIHRoZXkgYXJlLiBXZSBjYW4gb2J0YWluIHRoYXQgaW5mb3JtYXRpb24gYnkgY3JlYXRpbmcgYSBzdW1tYXJ5IG9mIHRoZSByYW5raW5nIGRhdGEgZnJhbWUgd2UgY3JlYXRlZC4gDQpgYGB7cn0NCmxpYnJhcnkocG1yKQ0KdGVzdCA8LSByYW5rYWdnKHJhbmsuZGF0YSkNCnRlc3QNCmBgYA0KDQpUaGUgbWF0cml4IHdlIHJlY2VpdmVkIGFzIGFuIG91dHB1dCBpcyB0aGUgc3VtbWFyeSBvZiBvdXIgcmFua2luZyBkYXRhLiBJdCBzaG93cyB0aGF0LCBmb3IgaW5zdGFuY2UsIHRoZSBwcmVmZXJlbmNlIGNvbWJpbmF0aW9uICIyLDEsMyw0LDUiIHJlcGVhdHMgMTAgdGltZXMgaW4gdGhlIGRhdGEgZnJhbWUuIE1vcmUgc3BlY2lmaWNhbGx5LCBpdCBtZWFucyB0aGF0IHRoZXJlIGFyZSAxMCByZXNwb25kZW50cyB3aG8gcHJlZmVyIHRoZSBpdGVtIDIoIkNhbG9yaWVzIGJ1cm5lZCIpIHRoZSBtb3N0LCB0aGVuIHRoZSBpdGVtIDEoIk1lYXN1cmluZyBzdGVwcyIpLCBhbmQgc28gb24uDQoNCk5vdyB3ZSBjYW4gY2FsY3VsYXRlIHRoZSBtZWFuIHJhbmsgZm9yIGVhY2ggZmVhdHVyZSBhbmQgY29uY2x1ZGUgd2hpY2ggZmVhdHVyZSBpcyB0aGUgbW9zdCBpbXBvcnRhbnQgdG8gb3VyIHJlc3BvbmRlbnRzOg0KDQpgYGB7cn0NCiMgTWVhbiByYW5rIG9mIGVhY2ggZml0bmVzcyB0cmFja2VyIGZlYXR1cmUNCmRlc3RhdCh0ZXN0KSRtZWFuLnJhbmsNCmBgYA0KDQpBcyB3ZSBjYW4gb2JzZXJ2ZSBmcm9tIHRoZSBvdXRwdXQsIHRoZSBpdGVtIDEoIk1lYXN1cmluZyBzdGVwcyIpIHNob3dzIHRoZSBiZXN0IG1lYW4gcmFuayBhbW9uZyBhbGwgaXRlbXMuIFRoZXJlZm9yZSwgd2UgY2FuIGFzc3VtZSB0aGF0IHRoZSAiTWVhc3VyaW5nIHN0ZXBzIiBpcyBtb3N0IGltcG9ydGFudCBmb3Igb3VyIHJlc3BvbmRlbnRzLiBIb3dldmVyLCBpbiBvcmRlciB0byBzdGF0aXN0aWNhbGx5IHByb3ZlIGl0IGFuZCBiZWNvbWUgc3VyZSB0aGF0IHRoaXMgaXMgbm90IGp1c3QgYnkgbWVyZSBjaGFuY2UsIHdlIGNhbiBjb25kdWN0ICoqRnJpZWRtYW4gcmFuayBzdW0gdGVzdCoqLg0KDQpGcmllZG1hbiByYW5rIHN1bSB0ZXN0IGlzIHVzZWQgdG8gaWRlbnRpZnkgd2hldGhlciB0aGVyZSBhcmUgYW55IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgZGlzdHJpYnV0aW9ucyBvZiAzIG9yIG1vcmUgcGFpcmVkIGdyb3Vwcy4gSXQgaXMgdXNlZCB3aGVuIHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbnMgZm9yIHVzaW5nIG9uZS13YXkgcmVwZWF0ZWQgbWVhc3VyZXMgQU5PVkEgYXJlIG5vdCBtZXQuIEFub3RoZXIgY2FzZSB3aGVuIEZyaWVkbWFuIHJhbmsgcnVtIHRlc3QgaXMgdXNlZCBpcyB3aGVuIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgaXMgbWVhc3VyZWQgb24gYW4gb3JkaW5hbCBzY2FsZSwgYXMgaW4gb3VyIGNhc2UuDQoNCkJlZm9yZSB3ZSBjb25kdWN0IHRoZSBGcmllZG1hbiByYW5rIHN1bSB0ZXN0LCB3ZSB3aWxsIHZpc3VhbGlzZSBvdXIgZGF0YToNCmBgYHtyLGVjaG89RkFMU0V9DQojIFByZXBhcmluZyBkYXRhIGZyYW1lIGZvciBGcmllZG1hbiByYW5rIHN1bSB0ZXN0DQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeShnZ3B1YnIpDQpsaWJyYXJ5KHJzdGF0aXgpDQpsaWJyYXJ5KGdnc3RhdHNwbG90KQ0KYGBgDQoNCg0KYGBge3J9DQojIFdlIGhhdmUganVzdCB0dXJuZWQgb3VyIGRhdGEgZnJhbWUgZnJvbSB0aGUgd2lkZSBmb3JtYXQgdG8gdGhlIGxvbmcgZm9ybWF0IGJ5IHVzaW5nIGZ1bmN0aW9uIG1lbHQoKS4gSWYgd2UgdGFrZSBhIGxvb2sgYXQgaGVhZCBhbmQgdGFpbCBvZiBvdXIgbmV3IGRhdGEgZnJhbWUsIHdlIGNhbiBzZWUgdGhhdCBpdCBjb250YWlucyBqdXN0IHR3byBjb2x1bW5zLCAiUmFuayIgYW5kICJGZWF0dXJlIi4NCg0KcmFuay5kYXRhLmxvbmcgPC0gcmVzaGFwZTI6Om1lbHQocmFuay5kYXRhLHZhbHVlLm5hbWUgPSAiUmFuayIsdmFyaWFibGUubmFtZSA9ICJGZWF0dXJlIiwgc3RyaW5nc0FzRmFjdG9ycz1UUlVFKQ0KDQp0YWlsKHJhbmsuZGF0YS5sb25nKQ0KaGVhZChyYW5rLmRhdGEubG9uZykNCg0KIyBWaXN1YWxpc2F0aW9uDQpnZ3N0YXRzcGxvdDo6Z2d3aXRoaW5zdGF0cygNCiAgZGF0YSA9IHJhbmsuZGF0YS5sb25nLA0KICB4ID0gRmVhdHVyZSwNCiAgeSA9IFJhbmssDQogIHR5cGUgPSAibnAiLA0KICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IFRSVUUsICMgc2hvdyBwYWlyd2lzZSBjb21wYXJpc29uIHRlc3QgcmVzdWx0cw0KICB0aXRsZSA9ICJXaGF0IGZlYXR1cmVzIGFyZSBpbXBvcnRhbnQgdG8geW91IHdoZW4gZXZ1YWx0aW5nIGZpdG5lc3MgdHJhY2tlcnM/IikNCmBgYA0KDQpBbHJlYWR5IGZyb20gdGhlIGFkdmFuY2VkIHZpc3VhbGlzYXRpb24sIHRoYXQgaW5jbHVkZXMgRnJpZWRtYW4gcmFuayBzdW0gdGVzdCBhbmQgcGFpcndpc2UgY29tcGFyaXNvbiwgd2UgY2FuIGhhdmUgYW4gaW5zaWdodCBpbiBzaWduaWZpY2FuY2Ugb2YgZGlmZmVyZW5jZXMgYW1vbmcgZmVhdHVyZXMuICANCg0KYGBge3J9DQojIEZyaWVkbWFuIHRlc3QgDQpmcmllZG1hbi50ZXN0KGFzLm1hdHJpeChyYW5rLmRhdGEpKQ0KYGBgDQoNCkZyaWVkbWFuIHJhbmsgc3VtIHRlc3QgaGFzIGEgcC12YWx1ZSBsb3dlciB0aGFuIDAuMDUsIHNvIHdlIGNhbiBjb25jbHVkZSB0aGF0IGhlcmUgYXJlIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGJldHdlZW4gYXQgbGVhc3QgdHdvIGZlYXR1cmVzICh3aGF0IHdlIGhhdmUgYWxyZWFkeSBzZWVuIGluIG91ciB2aXN1YWxpc2F0aW9uKS4gRXZlbiB0aG91Z2ggd2UgaGF2ZSBpZGVudGlmaWVkIGRpZmZlcmVuY2VzIGJldHdlZW4gcHJlZmVyZW5jZXMgdG93YXJkcyBmZWF0dXJlcyBpbiBvdXIgYWR2YW5jZWQgdmlzdWFsaXNhdGlvbiwgd2Ugd2lsbCBjb25kdWN0IGEgcG9zdCBob2MgdGVzdCBpbiBvcmRlciB0byBkZW1vbnN0cmF0ZSB0cmFkaXRpb25hbCB3YXkgb2YgY2FsY3VsYXRpbmcgcGFpcndpc2UgY29tcGFyaXNvbnMuDQoNCg0KYGBge3J9DQprbml0cjo6a2FibGUod2lsY294X3Rlc3QoUmFuayB+IEZlYXR1cmUsIHBhaXJlZCA9IFRSVUUsIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIiwgZGF0YSA9IHJhbmsuZGF0YS5sb25nKSkNCmBgYA0KVGhlIG91dHB1dCB0YWJsZSBwcm92aWRlcyB1cyB3aXRoIHAtdmFsdWVzIHJlZmVycmluZyB0byBzaWduaWZpY2FuY2Ugb2YgZGlmZmVyZW5jZSBpbiBtZWFuIHJhbmtzIG9mIGVhY2ggcGFpci4gRm9yIGluc3RhbmNlLCB0aGUgZmlyc3QgNCByb3dzICBwcm92ZXMgdGhhdCB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgbWVhbiByYW5rIG9mIHRoZSBmZWF0dXJlICJNZWFzdXJpbmcgc3RlcHMiIGFuZCBlYWNoIG9mIHRoZSByZXN0IG9mIGZlYXR1cmVzIGFyZSBzaWduaWZpY2FudC4gQ29uc2VxdWVudGx5LCB3ZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGlzIGZlYXR1cmUgaXMgYnkgZmFyIHRoZSBtb3N0IGltcG9ydGFudCBhbW9uZyBvdXIgcmVzcG9uZGVudHMuIA0KDQoNCkFub3RoZXIgcXVlc3Rpb24gdGhhdCBtYXkgYmUgaW50ZXJlc3RpbmcgdG8gZXhwbG9yZSBpcyB3aGV0aGVyIHRoZXJlIGFyZSBhbnkgY29tcGxlbWVudGFyeSBmZWF0dXJlcyA/IE9yIGZlYXR1cmVzIHdoaWNoIG92ZXJsYXAgZWFjaCBvdGhlciBpbiBpdHMgZnVuY3Rpb25hbGl0eT8gSW4gb3JkZXIgdG8gaGF2ZSBhIGxvb2sgYXQgdGhhdCwgd2UgY2FuIGludmVzdGlnYXRlIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHJhbmtzIGFzc2lnbmVkIHRvIGVhY2ggZmVhdHVyZS4NCmBgYHtyfQ0KI0NvcnJlbGF0aW9uIE1hdHJpeA0KY29yLm1hdHJpeDwtY29yKHJhbmsuZGF0YSwgbWV0aG9kPWMoJ3NwZWFybWFuJykpDQpjb3IubWF0cml4DQpgYGANCg0KQXQgdGhlIGZpcnN0IGdsYW5jZSB3ZSBjYW4gb2JzZXJ2ZSBhIGxvdCBvZiBuZWdhdGl2ZSB2YWx1ZXMsIG1lYW5pbmcgdGhhdCBtYW55IGZlYXR1cmVzIGNvcnJlbGF0ZSBuZWdhdGl2ZWx5IHJlbGF0aXZlIHRvIGVhY2ggb3RoZXIuIEluIG9yZGVyIHRvIG1ha2UgdGhlIGludGVycHJldGF0aW9uIGVhc2llciwgd2Ugd2lsbCB0cnkgdG8gdmlzdWFsaXNlIGNvcnJlbGF0aW9ucyBpbiBhIGZvcm0gb2YgYSBjb3JyZWxhdGlvbiBtYXRyaXguDQoNCmBgYHtyfQ0KbGlicmFyeShnZ2NvcnJwbG90KQ0KZ2djb3JycGxvdChjb3IubWF0cml4KQ0KYGBgDQoNCkZyb20gdGhlIGNvcnJlbGF0aW9uIG1hdHJpeCB3ZSBjYW4gY29uZmlybSB0aGF0IGFsbW9zdCBhbGwgZmVhdHVyZXMgbmVnYXRpdmVseSBjb3JyZWxhdGUgdG8gZWFjaCBvdGhlci4gQW4gZXhjZXB0aW9uIGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBmZWF0dXJlICJNZWFzdXJpbmcgc3RlcHMiIGFuZCAiRXhlcmNpc2UgdHJhY2tpbmciLCB3aGljaCBjb3JyZWxhdGVzIHBvc2l0aXZlbHkuIFRoaXMgbWF0cml4IGNhbiBiZSB1c2VmdWwgZm9yIGRpZ2dpbmcgZGVlcGVyIGluIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByZWZlcmVuY2VzIGZvciBmZWF0dXJlcy4gRm9yIGluc3RhbmNlLCB3ZSBjYW4gYXNzdW1lIHRoYXQgZmVhdHVyZSAiTWVhc3VyaW5nIHN0ZXBzIiBhbmQgIkV4ZXJjaXNlIHRyYWNraW5nIiBjb3JyZWxhdGUgcG9zaXRpdmVseSBiZWNhdXNlIHVzZXJzIHNlZSB0aGVtIGFzIGNvbXBsZW1lbnRhcnkgZmVhdHVyZXMuIE1vcmVvdmVyLCBpZiB3ZSBzYXkgdGhhdCB3YWxraW5nIGlzIGEgdHlwZSBvZiBleGVyY2lzZSAoaW4gY2FzZSBvZiBsb25nZXIgd2Fsa2luZyByb3V0ZXMpLCB3ZSBjYW4gYXNzdW1lIHRoYXQgdXNlcnMsIHdobyByYW5rZWQgIkV4ZXJjaXNlIHRyYWNraW5nIiBoaWdoLCByYW5rZWQgIk1lYXN1cmluZyBzdGVwcyIgaGlnaCBhcyB3ZWxsLCBiZWNhdXNlIHRoZXkgcGVyY2VpdmUgaXQgYXMgYW5vdGhlciB0eXBlIG9mICJFeGVyY2lzZSB0cmFja2luZyIuDQoNCiMjIyBDb25zdGFudCBTdW0gcXVlc3Rpb24gey19DQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnY29uc3RhbnQtc3VtLXF1ZXN0aW9uLnBuZycpDQpgYGANCg0KSWYgeW91IHdpc2ggdG8gb2J0YWluIGluZm9ybWF0aW9uIGFib3V0IGhvdyBtdWNoIG9uZSBhdHRyaWJ1dGUgaXMgcHJlZmVycmVkIG92ZXIgYW5vdGhlciBvbmUsIHlvdSBtYXkgdXNlIGEgY29uc3RhbnQgc3VtIHNjYWxlLiBUaGUgdG90YWwgYm94IHNob3VsZCBhbHdheXMgYmUgZGlzcGxheWVkIGF0IHRoZSBib3R0b20gdG8gbWFrZSBpdCBlYXNpZXIgZm9yIHJlc3BvbmRlbnRzLiBBIGNvbnN0YW50IHN1bSBxdWVzdGlvbiBwZXJtaXRzIGNvbGxlY3Rpb24gb2YgcmF0aW8gZGF0YSB0eXBlLiBXaXRoIGRhdGEgb2J0YWluZWQgd2Ugd291bGQgYmUgYWJsZSB0byBleHByZXNzIHRoZSByZWxhdGl2ZSBpbXBvcnRhbmNlIG9mIHRoZSBvcHRpb25zLg0KDQpgYGB7ciwgZWNobz1GQUxTRSx3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQ0KY29uc3RhbnQuc3VtIDwtIHN1YnNldChxdWFsdHJpY3MsIHNlbGVjdCA9YygiIExvY2F0aW9uIiwiIFByaWNlIiwiIEFtYmllbmNlIiwiIEN1c3RvbWVyIFNlcnZpY2UiKSkNCmNvbnN0YW50LnN1bSRpZCA8LSBzZXEoMTpucm93KGNvbnN0YW50LnN1bSkpDQprbml0cjo6a2FibGUoY29uc3RhbnQuc3VtWzE6NixdLCBjYXB0aW9uID0gIkNvbnN0YW50IFN1bSBRdWVzdGlvbiIpDQpgYGANCg0KYGBge3J9DQojIENvbXB1dGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcw0KbGlicmFyeShwYXN0ZWNzKSANCnJlcyA8LSBzdGF0LmRlc2MoY29uc3RhbnQuc3VtKQ0Kcm91bmQocmVzWywxOjRdLDIpDQpgYGANCg0KYGBge3IsZXJyb3I9RkFMU0Usd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgQ3JlYXRpb24gb2YgdGhlIGxvbmcgdmVyc2lvbiBvZiBkYXRhIGZyYW1lDQpjb25zdGFudC5zdW0ubG9uZyA8LW1lbHQoY29uc3RhbnQuc3VtWywtNV0sIHZhcmlhYmxlLm5hbWUgPSJGYWN0b3IiICx2YWx1ZS5uYW1lID0gIlBvaW50cyIpDQpjb25zdGFudC5zdW0ubG9uZw0KYGBgDQoNCg0KYGBge3IsZXJyb3I9RkFMU0Usd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgQm94cGxvdCBnZ3Bsb3QyDQpwPC1jb25zdGFudC5zdW0ubG9uZyAlPiUgDQogIGZpbHRlcihGYWN0b3IhPSJpZCIpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9RmFjdG9yLCB5PVBvaW50cywgZmlsbD0gRmFjdG9yKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJXaGF0IGZhY3RvcnMgZG8geW91IGNvbnNpZGVyIHdoZW4gY2hvb3NpbmcgYSBwbGFjZSB0byBnbyBmb3IgYSBkaW5uZXI/IikgKw0KICAgIHhsYWIoIiIpDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCldpdGggdGhlIGRhdGEgY29sbGVjdGVkIHdlIGFyZSBhYmxlIHRvIGFuc3dlciB0aGUgcXVlc3Rpb246IHdoYXQgZmFjdG9yIGlzIHRoZSBtb3N0IGltcG9ydGFudCBmb3Igb3VyIHJlc3BvbmRlbnRzIHdoZW4gdGhleSBnbyBvdXQgZm9yIGEgZGlubmVyPw0KDQpgYGB7cn0NCmxpYnJhcnkocm9iQ29tcG9zaXRpb25zKQ0KY29uc3RTdW0oY29uc3RhbnQuc3VtLDEwMClbLC01XQ0KYGBgDQoNCkluIG9yZGVyIHRvIGFud3NlciB0aGlzIHF1ZXN0aW9uIHdlIG5lZWQgdG8gY29uZHVjdCAqKmEgcmVwZWF0ZWQgbWVhc3VyZXMgQU5PVkEqKi4NClRoaXMgdHlwZSBvZiBBTk9WQSBpcyB1c2VkIGZvciBhbmFseXppbmcgZGF0YSB3aGVyZSB0aGUgc2FtZSBzdWJqZWN0cyBhcmUgbWVhc3VyZWQgbW9yZSB0aGFuIG9uY2UuIEluIG91ciBjYXNlIHdlIGhhdmUgZXZlcnkgcmVzcG9uZGVudCBtZWFzdXJlZCBvbiBlYWNoIG9mIHRoZSBmYWN0b3JzIChsb2NhdGlvbnMsIHByaWNlLCBhbWJpZW5jZSBhbmQgY3VzdG9tZXIgc2VydmljZSkuIFJlcGVhdGVkIG1lYXN1cmVzIEFOT1ZBIGlzIGFuIGV4dGVuc2lvbiBvZiB0aGUgcGFpcmVkLXNhbXBsZXMgdC10ZXN0LiBUaGlzIHRlc3QgaXMgYWxzbyByZWZlcnJlZCB0byBhcyBhIHdpdGhpbi1zdWJqZWN0cyBBTk9WQS4gSW4gdGhlIHdpdGhpbi1zdWJqZWN0IGV4cGVyaW1lbnRhbCBkZXNpZ24gdGhlIHNhbWUgaW5kaXZpZHVhbHMgYXJlIG1lYXN1cmVkIG9uIHRoZSBzYW1lIG91dGNvbWUgdmFyaWFibGUgdW5kZXIgZGlmZmVyZW50IHRpbWUgcG9pbnRzIG9yIGNvbmRpdGlvbnMuDQoNCldlIG5lZWQgdG8gY2hlY2sgYWxsIGFzc3VtcHRpb25zIHRoYXQgbmVlZCB0byBiZSBmdWxmaWxsZWQgaW4gb3JkZXIgdG8gZGVwbG95IHRoaXMgdHlwZSBvZiBBTk9WQS4gVGhlcmUgYXJlIHRocmVlIGFzc3VtcHV0aW9ucyB0aGF0IG5lZWQgdG8gY2hlY2suIFRoZSBmaXJzdCB0byBjaGVjayB0aGF0IGVhY2ggbGV2ZWwgb2YgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlIGlzIGFwcHJveGltYXRlbHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFNpbmNlIHdlIGhhdmUgbW9yZSB0aGFuIDMwIG9ic2VydmF0aW9ucyBhdCBlYWNoIGxldmVsLCB3ZSBkbyBub3QgbmVlZCB0byBwcm9jZWVkIGZ1cnRoZXIgZHVlIHRvIHRoZSBjZW50cmFsIGxpbWl0IHRoZW9yZW0uIFNlY29uZCBhc3N1bXB0aW9uIHJlZmVycnMgdG8gZXh0cmVtZSBvdXRsaWVycy4gTGV0J3MgaGF2ZSBhIGxvb2sgYXQgcG90ZW50aWFsIG91dGxpZXJzOg0KDQpgYGB7cn0NCiMgT3V0bGllcnMNCmNvbnN0YW50LnN1bS5sb25nICU+JSANCiAgZ3JvdXBfYnkoRmFjdG9yKSAlPiUNCiAgaWRlbnRpZnlfb3V0bGllcnMoUG9pbnRzKQ0KYGBgDQoNCkFzIHdlIGNhbm5vdCBpZGVudGlmeSBhbnkgZXh0cmVtZSBvdXRsaWVycywgd2UgY2FuIHByb2NlZWQgd2l0aCBkZXBsb3lpbmcgcmVwZWF0ZWQgbWVhc3VyZXMgQU5PVkEuDQoNCmBgYHtyfQ0KIyBGb3JtYXR0aW5nIGRhdGEgDQpjb25zdGFudC5zdW0uYW92IDwtIGdhdGhlcihjb25zdGFudC5zdW0sIGtleSA9ICJGYWN0b3IiLCB2YWx1ZSA9ICJQb2ludHMiLCBgIExvY2F0aW9uYCxgIFByaWNlYCxgIEFtYmllbmNlYCxgIEN1c3RvbWVyIFNlcnZpY2VgKQ0KDQojIE9uZS13YXkgcmVwZWF0ZWQgbWVhc3VyZXMgQU5PVkEgIA0KcmVzLmFvdiA8LSBhbm92YV90ZXN0KGRhdGEgPSBjb25zdGFudC5zdW0uYW92LCBkdiA9IFBvaW50cyx3aWQgPSBpZCAsd2l0aGluID0gRmFjdG9yKQ0KZ2V0X2Fub3ZhX3RhYmxlKHJlcy5hb3YpDQoNCiMgUG9zdCBob2MgdGVzdA0KcGFpcndpc2UudC50ZXN0KGNvbnN0YW50LnN1bS5sb25nJFBvaW50cyxjb25zdGFudC5zdW0ubG9uZyRGYWN0b3IsIHBhaXJlZCA9IFQsIHAuYWRqdXN0Lm1ldGhvZCA9ICJob2xtIikNCmBgYA0KTm93IHdlIGNhbiBjbGVhcmx5IHNlZSB0aGF0IG91ciByZXNwb25kZW50cyBjb25zaWRlciBwcmljZSBtb3JlIHRoYW4gbG9jYXRpb24sIG9yIGFtYmllbmNlLCB3aGlsZSBjdXN0b21lciBzZXJ2aWNlIGlzIHBlcmNlaXZlZCBhbG1vc3QgZXF1YWxseSBpbXBvcnRhbnQgYXMgcHJpY2VzLg0KDQpgYGB7cn0NCmdnc3RhdHNwbG90OjpnZ3dpdGhpbnN0YXRzKA0KICBkYXRhID0gY29uc3RhbnQuc3VtLmxvbmcgJT4lIGZpbHRlcihGYWN0b3IhPSJpZCIpLCAjIGV4Y2x1ZGluZyAiaWQiIGNvbHVtbiBmcm9tIHRoZSBkYXRhDQogIHggPSBGYWN0b3IsDQogIHkgPSBQb2ludHMsDQogIHR5cGUgPSAicCIsDQogIHBhaXJ3aXNlLmNvbXBhcmlzb25zID0gVFJVRSwgIyBzaG93IHBhaXJ3aXNlIGNvbXBhcmlzb24gdGVzdCByZXN1bHRzDQogIHRpdGxlID0gIldoYXQgZmFjdG9ycyBkbyB5b3UgY29uc2lkZXIgd2hlbiBjaG9vc2luZyBhIHBsYWNlIHRvIGdvIGZvciBhIGRpbm5lcj8iKQ0KYGBgDQoNCiMjIyBUZXh0IG9yIG51bWJlciBlbnRyeSBxdWVzdGlvbiB7LX0NCg0KYGBge3IsZWNobz1GQUxTRX0NCnNldC5zZWVkKDEyMzQ1NjcpDQpxdWFsdHJpY3MkYCBXaWxsaW5nbmVzcy10by1wYXkgKGluIEVVUilgPC0gYWJzKGFzLmludGVnZXIocm5vcm0obiA9IDExNyxtZWFuPTIzLHNkPTQwKSkpDQpxdWFsdHJpY3MkYCBDdXN0b21lciBTZXJ2aWNlYCA8LSBhYnMoYXMuaW50ZWdlcihydW5pZihuPTExNyxtaW49MCxtYXggPSAxMDApKSkNCmBgYA0KDQoNCkEgdGV4dCBvciBudW1iZXIgZW50cnkgcXVlc3Rpb24gaXMgYSByZWNvbW1lbmRlZCB0eXBlIG9mIHF1ZXN0aW9uIGlmIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiBvYnRhaW5pbmcgcmF0aW8gZGF0YSB0eXBlLiBXZSB3aWxsIHVzZSB0aGlzIHR5cGUgb2YgcXVlc3Rpb24gdG9nZXRoZXIgd2l0aCBhIGNvbnN0YW50IHN1bSBxdWVzdGlvbiB0eXBlIHRvIGNvbGxlY3QgZGF0YSB0aGF0IGNhbiBiZSBhbmFseXNlZCB3aXRoIHJlZ3Jlc3Npb24gYW5hbHlzaXMuIE5vdGUgdGhhdCBpbiB0aGlzIGNhc2Ugd2UgdHJlYXQgY29uc3RhbnQgc3VtIGRhdGEgYXMgcmF0aW8gZGF0YSBhbmQgdGhlcmVmb3JlIGFzc3VtZSB0aGF0IDAgbWVhbnMgY29tcGxldGUgYWJzZW5jZS4gIA0KDQoNCkhlcmUgaXMgYSBnbGltcHNlIGluIGFuc3dlcnMgb24gaG93IGltcG9ydGFudCBpcyBlYWNoIGZhY3RvciB0byBvdXIgcmVzcG9uZGVudHMgd2hlbiBpdCBjb21lcyB0byBkaW5uaW5nIG91dHNpZGU6DQpgYGB7ciwgZWNobz0gRkFMU0V9DQprbml0cjo6a2FibGUocXVhbHRyaWNzWzE6NixjKCIgTG9jYXRpb24iLCIgUHJpY2UiLCIgQW1iaWVuY2UiLCIgQ3VzdG9tZXIgU2VydmljZSIpXSwgY2FwdGlvbiA9ICJDb25zdGFudCBzdW0gcXVlc3Rpb24iKQ0KYGBgDQoNCkFkZGl0aW9uYWxseSwgd2UgYXNrZWQgb3VyIHJlc3BvbmRlbnRzIGhvdyBtdWNoIGFyZSB0aGV5IHdpbGxpbmcgdG8gc3BlbmQgb24gZGlubmVyIG9uIGF2ZXJhZ2UuIEluIG9yZGVyIHRvIGhhbmRsZSBkYXRhIGVhc2llciwgd2Ugd2lsbCBjcmVhdGUgYSBuZXcgZGF0YSBmcmFtZSB3aGVyZSB3ZSBtZXJnZSBhbGwgdGhlIGRhdGEgdG9nZXRoZXI6DQpgYGB7cn0NCmRpbm5lciA8LSBzdWJzZXQocXVhbHRyaWNzLCBzZWxlY3QgPSBjKCIgTG9jYXRpb24iLCIgUHJpY2UiLCIgQW1iaWVuY2UiLCIgQ3VzdG9tZXIgU2VydmljZSIsICIgV2lsbGluZ25lc3MtdG8tcGF5IChpbiBFVVIpIikpDQprbml0cjo6a2FibGUoaGVhZChkaW5uZXIpKQ0KYGBgDQpCZWZvcmUgd2UgY29uZHVjdCBhIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzLCB3ZSBuZWVkIHRvIHRha2UgYSBsb29rIGF0IGNvcnJlbGF0aW9uIG1hdHJpeDogIA0KDQpgYGB7cn0NCmNvcnJlbGF0aW9uIDwtY29yKGRpbm5lciwgbWV0aG9kPWMoJ3BlYXJzb24nKSkNCmNvcnJlbGF0aW9uDQpgYGANCkZyb20gb3VyIGRhdGEgd2Ugc2VlLCBmb3IgaW5zdGFuY2UsIHRoYXQgc29tZSBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHdpbGxpbmduZXNzIHRvIHBheSBhbmQgaW1wb3J0YW5jZSBvZiBhbWJpYW5jZSBhcyB3ZWxsIGFzIHNvbWUgcG9zaXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBpbXBvcnRhbmNlIG9mIGN1c3RvbWVyIHNlcnZpY2UgYW5kIHdpbGxpbmduZXNzLXRvLXBheS4gTGV0IHVzIG9ic2VydmUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBhcyB3ZWxsOiAgDQpgYGB7cn0NCmtuaXRyOjprYWJsZShwc3ljaDo6ZGVzY3JpYmUoZGlubmVyKSkNCmBgYA0KDQpXZSBzZWUgdGhhdCBkaWZmZXJlbmNlIGJldHdlZW4gbWVhbiBhbmQgbWVkaWFuIGRvZXMgbm90IHN1Z2dlc3QgKGF0IHRoZSBmaXJzdCBzaWdodCkgZ3JlYXQgZWZmZWN0IG9mIG91dGxpZXJzLg0KTGV0IHVzIG5vdyBkbyBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpczoNCmBgYHtyfQ0KbWxyLmRpbm5lciA8LSBsbShgIFdpbGxpbmduZXNzLXRvLXBheSAoaW4gRVVSKWAgfiBgIExvY2F0aW9uYCArIGAgUHJpY2VgICsgYCBBbWJpZW5jZWArYCBDdXN0b21lciBTZXJ2aWNlYCwgZGF0YSA9IGRpbm5lcikNCnN1bW1hcnkobWxyLmRpbm5lcikNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmNvZWZmIDwtIHN1bW1hcnkobWxyLmRpbm5lcikNCmBgYA0KDQpPdXQgb2YgYWxsIGZhY3RvcnMgb2YgaW1wb3J0YW5jZSB3aGVuIGRpbm5pbmcgb3V0LCB0aGUgb25seSBvbmUgdGhhdCBzdWdnZXN0cyBzaWduaWZpY2FuY2UgYXQgMC4wNSBsZXZlbCBvZiBzaWduaWZpY2FuY2UgaXMgYW1iaWVuY2UuIEZyb20gdGhlIHN1bW1hcnkgd2UgY2FuIGNvbmNsdWRlIHRoYXQgaW5jcmVhc2UgaW4gaW1wb3J0YW5jZSBvZiBhbWJpZW5jZSBieSAxIHBvaW50LCBsZWFkcyB0byBkZWNyZWFzZSBpbiB3aWxsaW5nbmVzcyB0byBwYXkgYnkgYHIgc3VtbWFyeShtbHIuZGlubmVyKSRjb2VmZmljaWVudHNbNCwxXWAuDQoNCmBgYHtyfQ0KY29uZmludChtbHIuZGlubmVyKQ0KYGBgDQoNCkZyb20gY29uZmlkZW5jZSBpbnRlcnZhbHMsIFdlIGNhbiBjb25jbHVkZSB0aGF0IHdoZW4gd2UgZG8gbm90IGNvbnNpZGVyIGFueSBvZiBnaXZlbiBmYWN0b3JzIChsb2NhdGlvbiwgcHJpY2UsIGFtYmllbmNlIGFuZCBjdXN0b21lciBzZXJ2aWNlKSwgd2lsbGluZ25lc3MgdG8gcGF5ICB3aWxsIGJlIHNvbWV3aGVyZSBiZXR3ZWVuIGByIGNvbmZpbnQobWxyLmRpbm5lcilbMSwxXWBFVVIgYW5kIGByIGNvbmZpbnQobWxyLmRpbm5lcilbMSwyXWBFVVIuIEJlc2lkZXMgdGhhdCwgZm9yIGVhY2ggaW5jcmVhc2UgaW4gaW1wb3J0YW5jZSBvZiBkaW5uZXIgYW1iaWFuY2UgYnkgb25lIHBvaW50LCB0aGVyZSB3aWxsIGJlIGFuIGF2ZXJhZ2UgZGVjcmVhc2Ugb2Ygd2lsbGluZ25lc3MgdG8gcGF5IGJldHdlZW4gYHIgY29uZmludChtbHIuZGlubmVyKVs0LDFdYCBhbmQgYHIgY29uZmludChtbHIuZGlubmVyKVs0LDJdYC4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQ0KZ2djb2Vmc3RhdHMoeCA9IG1sci5kaW5uZXIsDQogICAgICAgICAgICB0aXRsZSA9ICJXaWxsaW5nbmVzcyB0byBwYXkgcHJlZGljdGVkIGJ5IGltcG9ydGFuY2Ugb2YgZmFjdG9ycyIpDQpgYGANCg0KDQpUaGVyZSBhcmUgY291cGxlIG9mIHRoaW5ncyB3ZSBuZWVkIHRvIGNvbnNpZGVyIHdoZW4gd2UgZG8gbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24uIE9uZSBvZiB0aGVtIGFyZSBwb3RlbnRpYWwgb3V0bGllcnMgaW4gb3VyIGRhdGEuIEhlcmUgd2UgaWRlbnRpZnkgYW5kIHZpc3VhbGl6ZSB0aGVtOg0KDQpgYGB7cn0NCiMgT3V0bGllcnMNCm91dGxpZXJfdmFsdWVzIDwtIGJveHBsb3Quc3RhdHMobWxyLmRpbm5lciRyZXNpZHVhbHMpJG91dCAgIyBvdXRsaWVyIHZhbHVlcy4NCm91dGxpZXJfdmFsdWVzDQpgYGANCg0KV2UgaWRlbnRpZmllZCBvYnNlcnZhdGlvbnMgdGhhdCBiZWxvbmcgdG8gb3V0bGllciB2YWx1ZXMuIFdlIGNhbiBldmVuIHZpc3VhbGl6ZSB0aGVtIHRvbzoNCg0KYGBge3J9DQpib3hwbG90KG1sci5kaW5uZXIkcmVzaWR1YWxzLCBtYWluPSJXaWxsaW5nbmVzIHRvIHBheSIsIGJveHdleD0wLjEpDQpgYGANCg0KSW4gYWRkaXRpb24sIHdlIG5lZWQgdG8gb2JzZXJ2ZSB3aGV0aGVyIHRoZXJlIGFyZSBhbnkgaW5mbHVlbnRpYWwgb2JzZXJ2YXRpb25zOg0KDQpgYGB7cn0NCnBsb3QobWxyLmRpbm5lciw0KQ0KYGBgDQoNCkEgcnVsZSBvZiB0aHVtYiB0byBkZXRlcm1pbmUgd2hldGhlciBhbiBvYnNlcnZhdGlvbiBzaG91bGQgYmUgY2xhc3NpZmllZCBhcyBpbmZsdWVudGlhbCBvciBub3QgaXMgdG8gbG9vayBmb3Igb2JzZXJ2YXRpb24gd2l0aCBhIENvb2vigJlzIGRpc3RhbmNlID4gMSAuV2Ugc2VlIGZyb20gdGhlIGdyYXBoIHRoYXQgdGhlcmUgYXJlIG5vIGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucy4NCg0KDQpBbm90aGVyIHRoaW5nIHRvIGNvbnNpZGVyIGlzIGxpbmVhcml0eSwgaS5lLiB0aGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgZGVwZW5kZW50IGFuZCB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgY2FuIGJlIHJlYXNvbmFibHkgYXBwcm94aW1hdGVkIGluIGxpbmVhciB0ZXJtczoNCg0KYGBge3J9DQojIExpbmVhciBzcGVjaWZpY2F0aW9uDQpsaWJyYXJ5KGNhcikNCmF2UGxvdHMobWxyLmRpbm5lcikNCmBgYA0KDQpJbiBvdXIgZXhhbXBsZSBpdCBkb2VzIG5vdCBzZWVtIHRoYXQgbGluZWFyIHJlbGF0aW9uc2hpcHMgY2FuIGJlIHJlYXNvbmFibHkgYXNzdW1lZCBmb3IgYWxsIHZhcmlhYmxlcy4NCg0KQXMgd2UgYWxyZWFkeSBsZWFybmVkLCBhbm90aGVyIGltcG9ydGFudCBhc3N1bXB0aW9uIG9mIHRoZSBsaW5lYXIgbW9kZWwgaXMgdGhhdCB0aGUgZXJyb3IgdGVybXMgaGF2ZSBhIGNvbnN0YW50IHZhcmlhbmNlIChpLmUuLCBob21vc2NlZGFzdGljaXR5KToNCmBgYHtyfQ0KIyBCcmV1c2NoLVBhZ2FuIFRlc3QNCmxpYnJhcnkobG10ZXN0KQ0KYnB0ZXN0KG1sci5kaW5uZXIpDQpgYGANCg0KVGhlIG51bGwgaHlwb3RoZXNpcyBmb3IgdGhpcyB0ZXN0IGlzIHRoYXQgdGhlIGVycm9yIHZhcmlhbmNlcyBhcmUgYWxsIGVxdWFsLCBhbmQgb3VyIHJlc3VsdCBpcyBpbnNpZ25pZmljYW50LiBUaGVyZWZvcmUsIHRoaXMgYXNzdW1wdGlvbiBpcyBtZXQuIA0KDQpBbm90aGVyIGFzc3VtcHRpb24gdG8gYmUgbWV0IGlzIHRoYXQgdGhlIGVycm9yIHRlcm0gaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIE9uZSB3YXkgdG8gY2hlY2sgZm9yIG5vcm1hbCBkaXN0cmlidXRpb24gb2YgdGhlIGRhdGEgaXMgdG8gZW1wbG95IHN0YXRpc3RpY2FsIHdpdGggdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBPbmUgb2YgdGhlc2UgaXMgYSBTaGFwaXJv4oCTV2lsayB0ZXN0Og0KDQpgYGB7cn0NCnNoYXBpcm8udGVzdChyZXNpZChtbHIuZGlubmVyKSkNCmBgYA0KDQpXaGVuIHRoZSBhc3N1bXB0aW9uIG9mIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGVycm9ycyBpcyBub3QgbWV0IChhcyBpdCBpcyBub3QgbWV0IGluIG91ciBjYXNlKSwgdGhpcyBtaWdodCBhZ2FpbiBiZSBkdWUgdG8gYSBtaXNzcGVjaWZpY2F0aW9uIG9mIHlvdXIgbW9kZWwsIGluIHdoaWNoIGNhc2UgaXQgbWlnaHQgaGVscCB0byB0cmFuc2Zvcm0geW91ciBkYXRhLg0KDQoNCkZpbmFsbHksIHdlIG5lZWQgdG8gY2hlY2sgZm9yIG11bHRpY29sbGluZWFyaXR5LCB0aGUgY2FzZSB3aGVuIHRoZXJlIGlzIGEgc3Ryb25nIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzOg0KDQpgYGB7cn0NCmNvcnJlbGF0aW9uIDwtY29yKGRpbm5lciwgbWV0aG9kPWMoJ3BlYXJzb24nKSkNCmNvcnJlbGF0aW9uDQpgYGANCg0KQnkgb2JzZXJ2aW5nIG91ciBjb3JyZWxhdGlvbiBtYXRyaXgsIHdlIGNhbiBzZWUgdGhhdCBub24gb2YgdGhlIGNvZWZmaWNpZW50cyBzdWdnZXN0IHZhbHVlcyBjbG9zZSB0byAwLjggb3IgMC45LiBDb25zZXF1ZW50bHksIHdlIGNvbmNsdWRlIHRoYXQgdGhlcmUgYXJlIG5vIGNvbmNlcm5zIHJlZ2FyZGluZyB0aGUgbXVsdGljb2xpbmVhcml0eSBiZXR3ZWVuIGluZGVwZW5kZW50IHZhcmlhYmxlcy4NCg0KDQojIyBSZXBvcnRpbmcgey19DQoNCiBpbnR0b3INCg0KDQoNCiMjIFByZXNlbnRhdGlvbiBndWlkZWxpbmVzICYgZ3JhZGluZyB7LX0NCg0KWW91ciBwZXJmb3JtYW5jZSBpbiB0aGlzIHBhcnQgd2lsbCBiZSBldmFsdWF0ZWQgYmFzZWQgb24gdGhlIGZvbGxvd2luZyBjcml0ZXJpYToNCg0KKiAqKkluZGl2aWR1YWwgUmVzcG9uc2liaWxpdHk6KioNCg0KICAgICsgR3JvdXAgbWVtYmVycyBzaG91bGQgcGxhbiB0byBzaGFyZSBwcmVzZW50YXRpb24gcmVzcG9uc2liaWxpdGllcyBhbmQgZmllbGQgcXVlc3Rpb25zIGVxdWFsbHkuDQogICAgKyBBbGwgbWVtYmVycyBvZiB0aGUgZ3JvdXAgbXVzdCBjb250cmlidXRlIHRvIHRoZSBwcmVzZW50YXRpb24uDQogICAgKyBJbmRpdmlkdWFsIGdyYWRlIGZvciBwcmVzZW50YXRpb24gYW5kIG9yYWwgcGFydGljaXBhdGlvbiBkdXJpbmcgdGhlIGNsYXNzLg0KICAgICsgVG8gZW5zdXJlIGFuIGVxdWFsIGNvbnRyaWJ1dGlvbiBvZiBncm91cCBtZW1iZXJzLCBhIHBlZXIgYXNzZXNzbWVudCB3aWxsIGJlIGNvbmR1Y3RlZCwgd2hpY2ggZW50ZXJzIGludG8gdGhlIGNvbXB1dGF0aW9uIG9mIHRoZSBpbmRpdmlkdWFsIGdyYWRlcyBmb3IgdGhlIGdyb3VwIHByb2plY3QuIA0KDQoqICoqUXVhbGl0eSBvZiBxdWVzdGlvbm5haXJlIGRlc2lnbjoqKg0KDQogICAgKyBTdXJ2ZXkgbWV0aG9kDQogICAgKyBRdWVzdGlvbiBzdHJ1Y3R1cmUgLyB3b3JkaW5nDQoNCiogKipEYXRhIEFuYWx5c2lzOioqDQoNCiAgICArIENsYXJpdHkgLyBhcHByb3ByaWF0ZW5lc3MNCiAgICArIENvbXBsZXRlbmVzcyAvIGFjY3VyYWN5DQogICAgDQoqICoqUHJlc2VudGF0aW9uOioqDQoNCiAgICArIEludHJvZHVjdGlvbi9wcm9ibGVtLCBhcHByb2FjaCwgc29sdXRpb24vaW5jbHVzaW9uDQoNCg0KDQojIyMgRmluYWwgcHJlc2VudGF0aW9uIGFuZCBzdWJtaXNzaW9uIHstfQ0KDQoNCmBgYHtyIGV2YWwgPSBUUlVFLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpteXRhYmxlX3N1YiA9IGRhdGEuZnJhbWUoDQogICAgRCA9IGMoIk5vdi4gMTYqIiwNCiAgICAgICAgICAgICAiTm92LiAyMyoiLA0KICAgICAgICAgICAgICJEZWMuIDciDQogICAgICAgICAgICAgKSwNCiAgICBUaW1lX0EgPSBjKA0KICAgICAgIjAxOjMwUE0gLSAwNDozMFBNIiwiMDE6MzBQTSAtIDA2OjMwUE0iLCIxMTo1OVBNIg0KICAgICksRGF0ZV9CID0gYygiTm92LiAxOCoiLA0KICAgICAgICAgICAgICJOb3YuIDI1KiIsDQogICAgICAgICAgICAgIkRlYy4gOSINCiAgICAgICAgICAgICApLA0KICAgIFRpbWVfQiA9IGMoDQogICAgICAiMDI6MDBQTSAtIDA1OjAwUE0iLCIwMzowMFBNIC0gMDg6MDBQTSIsIjExOjU5UE0iDQogICAgKSwNCiAgICBUYXNrID0gYyggICIqIENvYWNoaW5nOiBEYXRhIGhhbmRsaW5nIChsaXZlIHZpZGVvIGNvYWNoaW5nKSIsDQogICAgICAgICAgICAgICAiKiBDb2FjaGluZzogRGF0YSBhbmFseXNpcyAobGl2ZSB2aWRlbyBjb2FjaGluZykiLA0KICAgICAgICAgICAgICAgIiogU3VibWl0IHZpZGVvIHJlY29yZGluZyBvZiBwcmVzZW50YXRpb24gKHByZS1yZWNvcmRlZCkiDQogICAgICAgICAgICAgICApLA0KICAgIENoYXB0ZXJzID0gYygiIiwiIiwiIiksDQogICAgTGluayA9IGMoICAgICJUQkMiLA0KICAgICAgICAgICAgICAgICAiVEJDIiwNCiAgICAgICAgICAgICAgICAgIiINCiAgICAgICAgICAgICAgICAgKQ0KICAgICkNCg0KI3BhbmRlcjo6cGFuZGVyKG15dGFibGVfc3ViLCBrZWVwLmxpbmUuYnJlYWtzID0gVFJVRSwgc3R5bGUgPSAnZ3JpZCcsIGp1c3RpZnkgPSAnbGVmdCcpDQpteXRhYmxlX3N1YiAlPiUga2FibGUoZXNjYXBlID0gVCkgJT4lDQogIGthYmxlX3BhcGVyKGMoImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICJEYXRlcyBhbmQgdGltZXMgYXJlIGluZGljYXRlZCBmb3IgZ3JvdXBzIEEgYW5kIEIgcmVzcGVjdGl2ZWx5Lg0KICAgICAgICAgICBTZXNzaW9ucyBpbmRpY2F0ZWQgd2l0aCAnKicgYXJlIGdyb3VwIGNvYWNoaW5nIHNlc3Npb25zLiBTbG90cyBvZiA0NSBtaW4uIGFyZSBhc3NpZ25lZCB0byBlYWNoIGdyb3VwIHdpdGhpbiB0aGUgaW5kaWNhdGVkIHRpbWVzLiIsDQogICAgICAgICAgIGdlbmVyYWxfdGl0bGUgPSAiTm90ZTogIiwgDQogICAgICAgICAgIGZvb3Rub3RlX2FzX2NodW5rID0gVCwgdGl0bGVfZm9ybWF0ID0gYygiaXRhbGljIikNCiAgICAgICAgICAgKSANCiMlPiUgICByb3dfc3BlYyhjKDEsMyw2KSwgYmFja2dyb3VuZCA9ICIjRTBFMEUwIikNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg==